wp-typia 0.16.0 → 0.16.2
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/package.json +2 -2
- package/src/ui/README.md +26 -0
- package/src/ui/add-flow-model.ts +120 -0
- package/src/ui/add-flow.tsx +246 -183
- package/src/ui/alternate-buffer-lifecycle.ts +152 -0
- package/src/ui/create-flow-model.ts +125 -0
- package/src/ui/create-flow.tsx +172 -145
- package/src/ui/first-party-form-model.ts +62 -0
- package/src/ui/first-party-form.tsx +460 -0
- package/src/ui/lazy-flow.tsx +22 -17
- package/src/ui/migrate-flow-model.ts +126 -0
- package/src/ui/migrate-flow.tsx +177 -159
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "wp-typia",
|
|
3
|
-
"version": "0.16.
|
|
3
|
+
"version": "0.16.2",
|
|
4
4
|
"description": "Canonical CLI package for wp-typia scaffolding and project workflows",
|
|
5
5
|
"packageManager": "bun@1.3.11",
|
|
6
6
|
"type": "module",
|
|
@@ -65,7 +65,7 @@
|
|
|
65
65
|
"@bunli/tui": "0.6.0",
|
|
66
66
|
"@bunli/utils": "0.6.0",
|
|
67
67
|
"@wp-typia/api-client": "^0.4.2",
|
|
68
|
-
"@wp-typia/project-tools": "0.16.
|
|
68
|
+
"@wp-typia/project-tools": "0.16.1",
|
|
69
69
|
"better-result": "^2.7.0",
|
|
70
70
|
"react": "19.2.0",
|
|
71
71
|
"react-dom": "19.2.0",
|
package/src/ui/README.md
CHANGED
|
@@ -15,3 +15,29 @@ Constraints:
|
|
|
15
15
|
shell automation.
|
|
16
16
|
- `@wp-typia/project-tools` remains the runtime library; these screens should only
|
|
17
17
|
collect input and hand the resolved command state back to `wp-typia`.
|
|
18
|
+
|
|
19
|
+
Alternate-buffer lifecycle contract:
|
|
20
|
+
|
|
21
|
+
- `LazyFlow` owns pre-mount lifecycle safety for lazy loader failures and loading-time quit.
|
|
22
|
+
- Mounted flows must use the shared alternate-buffer lifecycle helper instead of ad hoc exit logic.
|
|
23
|
+
- `create`, `add`, and `migrate` must always call `runtime.exit()` on submit success, cancel, and quit.
|
|
24
|
+
- Runtime execution failures use exit-on-failure: report the error, then exit immediately.
|
|
25
|
+
|
|
26
|
+
First-party form interaction contract:
|
|
27
|
+
|
|
28
|
+
- `create`, `add`, and `migrate` use a shared first-party form layer instead of relying on `SchemaForm` field traversal.
|
|
29
|
+
- Small viewport safety is part of the `wp-typia` contract: active fields must stay inside a scrollable viewport and footer help must not overlap the form body.
|
|
30
|
+
- Keyboard traversal is owned locally by `wp-typia`.
|
|
31
|
+
- `Tab` / `Shift+Tab` move across the visible field order.
|
|
32
|
+
- Select fields handle arrow-key movement and preserve traversal when moving back out to the next field.
|
|
33
|
+
- Checkbox fields use `Space` / `Enter` to toggle without trapping focus.
|
|
34
|
+
- Hidden conditional fields must never keep focus or leak stale values into submit payloads.
|
|
35
|
+
- `Ctrl+S` submit must stay reachable through the shared first-party field layer, not only through Bunli's form-level hotkeys.
|
|
36
|
+
|
|
37
|
+
Regression and triage contract:
|
|
38
|
+
|
|
39
|
+
- The committed regression contract is the first-party model and layout test suite under `packages/wp-typia/tests`.
|
|
40
|
+
- `create-flow-layout.test.ts` keeps the small-viewport scroll model and checkbox-cluster ordering pinned.
|
|
41
|
+
- `tui-interaction-models.test.ts` keeps visible field ordering and submit sanitization pinned for `add` and `migrate`.
|
|
42
|
+
- The committed tests deliberately stop short of a repo-level PTY smoke because the alternate-buffer harness cost and flake surface outweighed the regression value for this round.
|
|
43
|
+
- If a future regression needs terminal-level confirmation, reproduce it from the real `wp-typia` command first before classifying it as a Bunli-level issue.
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
|
|
3
|
+
import {
|
|
4
|
+
FIRST_PARTY_SELECT_FIELD_BODY_HEIGHT,
|
|
5
|
+
FIRST_PARTY_TEXT_FIELD_BODY_HEIGHT,
|
|
6
|
+
getFirstPartyScrollTop,
|
|
7
|
+
getFirstPartyViewportHeight,
|
|
8
|
+
} from "./first-party-form-model";
|
|
9
|
+
|
|
10
|
+
export const addFlowSchema = z.object({
|
|
11
|
+
anchor: z.string().optional(),
|
|
12
|
+
block: z.string().optional(),
|
|
13
|
+
"data-storage": z.string().optional(),
|
|
14
|
+
kind: z
|
|
15
|
+
.enum(["block", "variation", "pattern", "binding-source", "hooked-block"])
|
|
16
|
+
.default("block"),
|
|
17
|
+
name: z.string().optional(),
|
|
18
|
+
"persistence-policy": z.string().optional(),
|
|
19
|
+
position: z.string().optional(),
|
|
20
|
+
template: z.string().optional(),
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
export type AddFlowValues = z.infer<typeof addFlowSchema>;
|
|
24
|
+
|
|
25
|
+
export type AddFieldName =
|
|
26
|
+
| "kind"
|
|
27
|
+
| "name"
|
|
28
|
+
| "template"
|
|
29
|
+
| "block"
|
|
30
|
+
| "anchor"
|
|
31
|
+
| "position"
|
|
32
|
+
| "data-storage"
|
|
33
|
+
| "persistence-policy";
|
|
34
|
+
|
|
35
|
+
const ADD_FIELD_ORDER = [
|
|
36
|
+
"kind",
|
|
37
|
+
"name",
|
|
38
|
+
"template",
|
|
39
|
+
"block",
|
|
40
|
+
"anchor",
|
|
41
|
+
"position",
|
|
42
|
+
"data-storage",
|
|
43
|
+
"persistence-policy",
|
|
44
|
+
] as const satisfies ReadonlyArray<AddFieldName>;
|
|
45
|
+
|
|
46
|
+
const ADD_FIELD_HEIGHTS: Record<AddFieldName, number> = {
|
|
47
|
+
anchor: FIRST_PARTY_TEXT_FIELD_BODY_HEIGHT,
|
|
48
|
+
block: FIRST_PARTY_SELECT_FIELD_BODY_HEIGHT,
|
|
49
|
+
"data-storage": FIRST_PARTY_SELECT_FIELD_BODY_HEIGHT,
|
|
50
|
+
kind: FIRST_PARTY_SELECT_FIELD_BODY_HEIGHT,
|
|
51
|
+
name: FIRST_PARTY_TEXT_FIELD_BODY_HEIGHT,
|
|
52
|
+
"persistence-policy": FIRST_PARTY_SELECT_FIELD_BODY_HEIGHT,
|
|
53
|
+
position: FIRST_PARTY_SELECT_FIELD_BODY_HEIGHT,
|
|
54
|
+
template: FIRST_PARTY_SELECT_FIELD_BODY_HEIGHT,
|
|
55
|
+
};
|
|
56
|
+
|
|
57
|
+
export function isAddPersistenceTemplate(template?: string): boolean {
|
|
58
|
+
return template === "persistence" || template === "compound";
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
export function getVisibleAddFieldNames(values: Partial<AddFlowValues>): Array<AddFieldName> {
|
|
62
|
+
switch (values.kind ?? "block") {
|
|
63
|
+
case "variation":
|
|
64
|
+
return ["kind", "name", "block"];
|
|
65
|
+
case "pattern":
|
|
66
|
+
return ["kind", "name"];
|
|
67
|
+
case "binding-source":
|
|
68
|
+
return ["kind", "name"];
|
|
69
|
+
case "hooked-block":
|
|
70
|
+
return ["kind", "name", "anchor", "position"];
|
|
71
|
+
case "block":
|
|
72
|
+
default:
|
|
73
|
+
return ADD_FIELD_ORDER.filter((name) => {
|
|
74
|
+
if (name === "data-storage" || name === "persistence-policy") {
|
|
75
|
+
return isAddPersistenceTemplate(values.template);
|
|
76
|
+
}
|
|
77
|
+
return name === "kind" || name === "name" || name === "template";
|
|
78
|
+
});
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
export function getAddViewportHeight(terminalHeight = 24): number {
|
|
83
|
+
return getFirstPartyViewportHeight(terminalHeight);
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
export function getAddScrollTop(options: {
|
|
87
|
+
activeFieldName: string | null;
|
|
88
|
+
values: Partial<AddFlowValues>;
|
|
89
|
+
viewportHeight: number;
|
|
90
|
+
}): number {
|
|
91
|
+
const { activeFieldName, values, viewportHeight } = options;
|
|
92
|
+
return getFirstPartyScrollTop({
|
|
93
|
+
activeFieldName,
|
|
94
|
+
fieldHeights: ADD_FIELD_HEIGHTS,
|
|
95
|
+
visibleFieldNames: getVisibleAddFieldNames(values),
|
|
96
|
+
viewportHeight,
|
|
97
|
+
});
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
export function sanitizeAddSubmitValues(values: AddFlowValues): Record<string, unknown> {
|
|
101
|
+
const visibleFields = new Set(getVisibleAddFieldNames(values));
|
|
102
|
+
const sanitized: Record<string, unknown> = {};
|
|
103
|
+
|
|
104
|
+
for (const fieldName of visibleFields) {
|
|
105
|
+
const value = values[fieldName];
|
|
106
|
+
if (typeof value === "string") {
|
|
107
|
+
const trimmed = value.trim();
|
|
108
|
+
if (trimmed.length > 0) {
|
|
109
|
+
sanitized[fieldName] = trimmed;
|
|
110
|
+
}
|
|
111
|
+
continue;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
if (value !== undefined && value !== null) {
|
|
115
|
+
sanitized[fieldName] = value;
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
return sanitized;
|
|
120
|
+
}
|
package/src/ui/add-flow.tsx
CHANGED
|
@@ -1,34 +1,95 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { createElement, useMemo } from "react";
|
|
2
2
|
|
|
3
|
-
import {
|
|
4
|
-
|
|
3
|
+
import {
|
|
4
|
+
Form,
|
|
5
|
+
type SelectOption,
|
|
6
|
+
useFormContext,
|
|
7
|
+
useTerminalDimensions,
|
|
8
|
+
} from "@bunli/tui";
|
|
5
9
|
import { HOOKED_BLOCK_POSITION_IDS } from "@wp-typia/project-tools";
|
|
6
|
-
import { z } from "zod";
|
|
7
10
|
|
|
8
11
|
import { executeAddCommand } from "../runtime-bridge";
|
|
12
|
+
import { useAlternateBufferLifecycle } from "./alternate-buffer-lifecycle";
|
|
13
|
+
import {
|
|
14
|
+
type AddFlowValues,
|
|
15
|
+
addFlowSchema,
|
|
16
|
+
getAddScrollTop,
|
|
17
|
+
getAddViewportHeight,
|
|
18
|
+
getVisibleAddFieldNames,
|
|
19
|
+
isAddPersistenceTemplate,
|
|
20
|
+
sanitizeAddSubmitValues,
|
|
21
|
+
} from "./add-flow-model";
|
|
22
|
+
import {
|
|
23
|
+
FirstPartyScrollBox,
|
|
24
|
+
FirstPartySelectField,
|
|
25
|
+
FirstPartyTextField,
|
|
26
|
+
} from "./first-party-form";
|
|
27
|
+
import { getWrappedFieldNeighbors } from "./first-party-form-model";
|
|
9
28
|
|
|
10
|
-
const
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
29
|
+
const kindOptions: SelectOption[] = [
|
|
30
|
+
{ name: "block", description: "Add a real block slice", value: "block" },
|
|
31
|
+
{
|
|
32
|
+
name: "variation",
|
|
33
|
+
description: "Add a variation to an existing block",
|
|
34
|
+
value: "variation",
|
|
35
|
+
},
|
|
36
|
+
{
|
|
37
|
+
name: "pattern",
|
|
38
|
+
description: "Add a PHP block pattern shell",
|
|
39
|
+
value: "pattern",
|
|
40
|
+
},
|
|
41
|
+
{
|
|
42
|
+
name: "binding-source",
|
|
43
|
+
description: "Add a shared block bindings source",
|
|
44
|
+
value: "binding-source",
|
|
45
|
+
},
|
|
46
|
+
{
|
|
47
|
+
name: "hooked-block",
|
|
48
|
+
description: "Add block.json hook metadata to an existing block",
|
|
49
|
+
value: "hooked-block",
|
|
50
|
+
},
|
|
51
|
+
];
|
|
20
52
|
|
|
21
|
-
|
|
53
|
+
const templateOptions: SelectOption[] = [
|
|
54
|
+
{ name: "basic", description: "Basic block scaffold", value: "basic" },
|
|
55
|
+
{
|
|
56
|
+
name: "interactivity",
|
|
57
|
+
description: "Interactivity API block scaffold",
|
|
58
|
+
value: "interactivity",
|
|
59
|
+
},
|
|
60
|
+
{
|
|
61
|
+
name: "persistence",
|
|
62
|
+
description: "Persistence-enabled block scaffold",
|
|
63
|
+
value: "persistence",
|
|
64
|
+
},
|
|
65
|
+
{
|
|
66
|
+
name: "compound",
|
|
67
|
+
description: "Compound parent + child scaffold",
|
|
68
|
+
value: "compound",
|
|
69
|
+
},
|
|
70
|
+
];
|
|
22
71
|
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
72
|
+
const dataStorageOptions: SelectOption[] = [
|
|
73
|
+
{
|
|
74
|
+
name: "custom-table",
|
|
75
|
+
description: "Dedicated custom table storage",
|
|
76
|
+
value: "custom-table",
|
|
77
|
+
},
|
|
78
|
+
{
|
|
79
|
+
name: "post-meta",
|
|
80
|
+
description: "Persist through post meta",
|
|
81
|
+
value: "post-meta",
|
|
82
|
+
},
|
|
83
|
+
];
|
|
84
|
+
|
|
85
|
+
const persistencePolicyOptions: SelectOption[] = [
|
|
86
|
+
{
|
|
87
|
+
name: "authenticated",
|
|
88
|
+
description: "Authenticated write policy",
|
|
89
|
+
value: "authenticated",
|
|
90
|
+
},
|
|
91
|
+
{ name: "public", description: "Public token policy", value: "public" },
|
|
92
|
+
];
|
|
32
93
|
|
|
33
94
|
const HOOKED_BLOCK_POSITION_DESCRIPTIONS: Record<
|
|
34
95
|
(typeof HOOKED_BLOCK_POSITION_IDS)[number],
|
|
@@ -40,180 +101,182 @@ const HOOKED_BLOCK_POSITION_DESCRIPTIONS: Record<
|
|
|
40
101
|
lastChild: "Insert as the last child of the anchor block",
|
|
41
102
|
};
|
|
42
103
|
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
104
|
+
type AddFlowProps = {
|
|
105
|
+
cwd: string;
|
|
106
|
+
initialValues: Partial<AddFlowValues>;
|
|
107
|
+
workspaceBlockOptions: Array<{
|
|
108
|
+
description: string;
|
|
109
|
+
name: string;
|
|
110
|
+
value: string;
|
|
111
|
+
}>;
|
|
112
|
+
};
|
|
46
113
|
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
114
|
+
type AddSelectFieldName = {
|
|
115
|
+
[K in keyof AddFlowValues]-?: AddFlowValues[K] extends string | undefined ? K : never;
|
|
116
|
+
}[keyof AddFlowValues];
|
|
117
|
+
|
|
118
|
+
function getAddNameLabel(kind?: string): string {
|
|
119
|
+
switch (kind) {
|
|
120
|
+
case "variation":
|
|
121
|
+
return "Variation name";
|
|
122
|
+
case "pattern":
|
|
123
|
+
return "Pattern name";
|
|
124
|
+
case "binding-source":
|
|
125
|
+
return "Binding source name";
|
|
126
|
+
case "hooked-block":
|
|
127
|
+
return "Target block";
|
|
128
|
+
case "block":
|
|
129
|
+
default:
|
|
130
|
+
return "Block name";
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
function AddFlowFields({
|
|
135
|
+
workspaceBlockOptions,
|
|
136
|
+
}: {
|
|
137
|
+
workspaceBlockOptions: AddFlowProps["workspaceBlockOptions"];
|
|
138
|
+
}) {
|
|
139
|
+
const { activeFieldName, values } = useFormContext();
|
|
140
|
+
const { height: terminalHeight = 24 } = useTerminalDimensions();
|
|
141
|
+
const addValues = values as Partial<AddFlowValues>;
|
|
142
|
+
const kind = addValues.kind ?? "block";
|
|
143
|
+
const template = addValues.template;
|
|
144
|
+
const viewportHeight = getAddViewportHeight(terminalHeight);
|
|
145
|
+
const scrollValues = useMemo(() => ({ kind, template }), [kind, template]);
|
|
146
|
+
const scrollTop = useMemo(
|
|
147
|
+
() =>
|
|
148
|
+
getAddScrollTop({
|
|
149
|
+
activeFieldName,
|
|
150
|
+
values: scrollValues,
|
|
151
|
+
viewportHeight,
|
|
152
|
+
}),
|
|
153
|
+
[activeFieldName, scrollValues, viewportHeight],
|
|
154
|
+
);
|
|
155
|
+
|
|
156
|
+
const visibleFields = new Set(getVisibleAddFieldNames(addValues));
|
|
157
|
+
const orderedVisibleFields = useMemo(() => getVisibleAddFieldNames(addValues), [addValues]);
|
|
158
|
+
const hookedBlockNameUsesSelect = kind === "hooked-block" && workspaceBlockOptions.length > 0;
|
|
159
|
+
const variationBlockUsesSelect = kind === "variation" && workspaceBlockOptions.length > 0;
|
|
160
|
+
|
|
161
|
+
return createElement(
|
|
162
|
+
FirstPartyScrollBox,
|
|
163
|
+
{ scrollTop, viewportHeight },
|
|
164
|
+
[
|
|
165
|
+
createElement(FirstPartySelectField, {
|
|
166
|
+
...getWrappedFieldNeighbors(orderedVisibleFields, "kind"),
|
|
167
|
+
key: "kind",
|
|
168
|
+
label: "Kind",
|
|
169
|
+
name: "kind" satisfies AddSelectFieldName,
|
|
170
|
+
options: kindOptions,
|
|
171
|
+
}),
|
|
172
|
+
visibleFields.has("name") && !hookedBlockNameUsesSelect
|
|
173
|
+
? createElement(FirstPartyTextField, {
|
|
174
|
+
...getWrappedFieldNeighbors(orderedVisibleFields, "name"),
|
|
175
|
+
key: `name-text:${kind}`,
|
|
176
|
+
label: getAddNameLabel(kind),
|
|
85
177
|
name: "name",
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
178
|
+
})
|
|
179
|
+
: null,
|
|
180
|
+
hookedBlockNameUsesSelect
|
|
181
|
+
? createElement(FirstPartySelectField, {
|
|
182
|
+
...getWrappedFieldNeighbors(orderedVisibleFields, "name"),
|
|
183
|
+
key: "name-select:hooked-block",
|
|
184
|
+
label: getAddNameLabel(kind),
|
|
185
|
+
name: "name" satisfies AddSelectFieldName,
|
|
186
|
+
options: workspaceBlockOptions,
|
|
187
|
+
})
|
|
188
|
+
: null,
|
|
189
|
+
visibleFields.has("template")
|
|
190
|
+
? createElement(FirstPartySelectField, {
|
|
191
|
+
...getWrappedFieldNeighbors(orderedVisibleFields, "template"),
|
|
192
|
+
key: "template",
|
|
90
193
|
label: "Template family",
|
|
91
|
-
name: "template",
|
|
92
|
-
options:
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
{
|
|
100
|
-
name: "persistence",
|
|
101
|
-
description: "Persistence-enabled block scaffold",
|
|
102
|
-
value: "persistence",
|
|
103
|
-
},
|
|
104
|
-
{
|
|
105
|
-
name: "compound",
|
|
106
|
-
description: "Compound parent + child scaffold",
|
|
107
|
-
value: "compound",
|
|
108
|
-
},
|
|
109
|
-
],
|
|
110
|
-
visibleWhen: (values) => values.kind === "block",
|
|
111
|
-
},
|
|
112
|
-
{
|
|
113
|
-
kind: "text",
|
|
114
|
-
label: "Variation name",
|
|
115
|
-
name: "name",
|
|
116
|
-
visibleWhen: (values) => values.kind === "variation",
|
|
117
|
-
},
|
|
118
|
-
{
|
|
119
|
-
kind: workspaceBlockOptions.length > 0 ? "select" : "text",
|
|
194
|
+
name: "template" satisfies AddSelectFieldName,
|
|
195
|
+
options: templateOptions,
|
|
196
|
+
})
|
|
197
|
+
: null,
|
|
198
|
+
visibleFields.has("block") && !variationBlockUsesSelect
|
|
199
|
+
? createElement(FirstPartyTextField, {
|
|
200
|
+
...getWrappedFieldNeighbors(orderedVisibleFields, "block"),
|
|
201
|
+
key: "block-text",
|
|
120
202
|
label: "Target block",
|
|
121
203
|
name: "block",
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
name: "name",
|
|
129
|
-
visibleWhen: (values) => values.kind === "pattern",
|
|
130
|
-
},
|
|
131
|
-
{
|
|
132
|
-
kind: "text",
|
|
133
|
-
label: "Binding source name",
|
|
134
|
-
name: "name",
|
|
135
|
-
visibleWhen: (values) => values.kind === "binding-source",
|
|
136
|
-
},
|
|
137
|
-
{
|
|
138
|
-
kind: workspaceBlockOptions.length > 0 ? "select" : "text",
|
|
204
|
+
})
|
|
205
|
+
: null,
|
|
206
|
+
variationBlockUsesSelect
|
|
207
|
+
? createElement(FirstPartySelectField, {
|
|
208
|
+
...getWrappedFieldNeighbors(orderedVisibleFields, "block"),
|
|
209
|
+
key: "block-select",
|
|
139
210
|
label: "Target block",
|
|
140
|
-
name: "
|
|
211
|
+
name: "block" satisfies AddSelectFieldName,
|
|
141
212
|
options: workspaceBlockOptions,
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
213
|
+
})
|
|
214
|
+
: null,
|
|
215
|
+
visibleFields.has("anchor")
|
|
216
|
+
? createElement(FirstPartyTextField, {
|
|
217
|
+
...getWrappedFieldNeighbors(orderedVisibleFields, "anchor"),
|
|
218
|
+
key: "anchor",
|
|
146
219
|
label: "Anchor block name",
|
|
147
220
|
name: "anchor",
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
221
|
+
})
|
|
222
|
+
: null,
|
|
223
|
+
visibleFields.has("position")
|
|
224
|
+
? createElement(FirstPartySelectField, {
|
|
225
|
+
...getWrappedFieldNeighbors(orderedVisibleFields, "position"),
|
|
226
|
+
key: "position",
|
|
152
227
|
label: "Hook position",
|
|
153
|
-
name: "position",
|
|
228
|
+
name: "position" satisfies AddSelectFieldName,
|
|
154
229
|
options: HOOKED_BLOCK_POSITION_IDS.map((position) => ({
|
|
155
|
-
name: position,
|
|
156
230
|
description: HOOKED_BLOCK_POSITION_DESCRIPTIONS[position],
|
|
231
|
+
name: position,
|
|
157
232
|
value: position,
|
|
158
233
|
})),
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
234
|
+
})
|
|
235
|
+
: null,
|
|
236
|
+
visibleFields.has("data-storage") && isAddPersistenceTemplate(template)
|
|
237
|
+
? createElement(FirstPartySelectField, {
|
|
238
|
+
...getWrappedFieldNeighbors(orderedVisibleFields, "data-storage"),
|
|
239
|
+
key: "data-storage",
|
|
163
240
|
label: "Data storage",
|
|
164
|
-
name: "data-storage",
|
|
165
|
-
options:
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
name: "post-meta",
|
|
173
|
-
description: "Persist through post meta",
|
|
174
|
-
value: "post-meta",
|
|
175
|
-
},
|
|
176
|
-
],
|
|
177
|
-
visibleWhen: (values) =>
|
|
178
|
-
values.kind === "block" &&
|
|
179
|
-
(values.template === "persistence" || values.template === "compound"),
|
|
180
|
-
},
|
|
181
|
-
{
|
|
182
|
-
kind: "select",
|
|
241
|
+
name: "data-storage" satisfies AddSelectFieldName,
|
|
242
|
+
options: dataStorageOptions,
|
|
243
|
+
})
|
|
244
|
+
: null,
|
|
245
|
+
visibleFields.has("persistence-policy") && isAddPersistenceTemplate(template)
|
|
246
|
+
? createElement(FirstPartySelectField, {
|
|
247
|
+
...getWrappedFieldNeighbors(orderedVisibleFields, "persistence-policy"),
|
|
248
|
+
key: "persistence-policy",
|
|
183
249
|
label: "Persistence policy",
|
|
184
|
-
name: "persistence-policy",
|
|
185
|
-
options:
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
title="Extend a wp-typia workspace"
|
|
216
|
-
/>
|
|
217
|
-
</>
|
|
250
|
+
name: "persistence-policy" satisfies AddSelectFieldName,
|
|
251
|
+
options: persistencePolicyOptions,
|
|
252
|
+
})
|
|
253
|
+
: null,
|
|
254
|
+
],
|
|
255
|
+
);
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
export function AddFlow({ cwd, initialValues, workspaceBlockOptions }: AddFlowProps) {
|
|
259
|
+
const { handleCancel, handleSubmit } = useAlternateBufferLifecycle("wp-typia add failed");
|
|
260
|
+
|
|
261
|
+
return (
|
|
262
|
+
<Form
|
|
263
|
+
initialValues={initialValues}
|
|
264
|
+
onCancel={handleCancel}
|
|
265
|
+
onSubmit={async (values) =>
|
|
266
|
+
handleSubmit(async () => {
|
|
267
|
+
const flags = sanitizeAddSubmitValues(values);
|
|
268
|
+
await executeAddCommand({
|
|
269
|
+
cwd,
|
|
270
|
+
flags,
|
|
271
|
+
kind: values.kind,
|
|
272
|
+
name: typeof flags.name === "string" ? flags.name : undefined,
|
|
273
|
+
});
|
|
274
|
+
})
|
|
275
|
+
}
|
|
276
|
+
schema={addFlowSchema}
|
|
277
|
+
title="Extend a wp-typia workspace"
|
|
278
|
+
>
|
|
279
|
+
<AddFlowFields workspaceBlockOptions={workspaceBlockOptions} />
|
|
280
|
+
</Form>
|
|
218
281
|
);
|
|
219
282
|
}
|