@shwfed/nuxt 0.11.7 → 0.11.8
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/dist/module.d.mts +1 -0
- package/dist/module.json +1 -1
- package/dist/runtime/components/fields.d.vue.ts +3 -5
- package/dist/runtime/components/fields.vue +2 -1
- package/dist/runtime/components/fields.vue.d.ts +3 -5
- package/dist/runtime/components/ui/button-configurator/ButtonConfiguratorDialog.vue +129 -6
- package/dist/runtime/components/ui/fields/Fields.d.vue.ts +6 -7
- package/dist/runtime/components/ui/fields/Fields.vue +11 -6
- package/dist/runtime/components/ui/fields/Fields.vue.d.ts +6 -7
- package/dist/runtime/components/ui/fields/slot-props.d.ts +7 -0
- package/dist/runtime/components/ui/fields/slot-props.js +0 -0
- package/dist/runtime/components/ui/fields-configurator/FieldsConfiguratorDialog.vue +51 -5
- package/dist/types.d.mts +2 -0
- package/package.json +1 -1
package/dist/module.d.mts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import * as _nuxt_schema from '@nuxt/schema';
|
|
2
2
|
export { FieldsInstance } from '../dist/runtime/components/fields-instance.js';
|
|
3
|
+
export { FieldsSlotProps } from '../dist/runtime/components/ui/fields/slot-props.js';
|
|
3
4
|
|
|
4
5
|
type Wrap<T> = T extends object ? Readonly<{
|
|
5
6
|
[P in keyof T]?: Wrap<T[P]>;
|
package/dist/module.json
CHANGED
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
import { Effect } from 'effect';
|
|
2
2
|
import { type FieldsConfigInput } from './ui/fields/Fields.vue.js';
|
|
3
|
+
import type { FieldsSlotProps } from './ui/fields/slot-props.js';
|
|
3
4
|
export { CalendarFieldC, EmptyFieldC, FieldC, FieldsBodyC, FieldsBodyInputC, FieldsConfigC, FieldsConfigInputC, NumberFieldC, SelectFieldC, SlotFieldC, StringFieldC, CURRENT_COMPATIBILITY_DATE, KIND, SUPPORTED_COMPATIBILITY_DATES, createFieldsConfig, } from './ui/fields/Fields.vue.js';
|
|
4
5
|
export type { EmptyField, Field, FieldsBody, FieldsBodyInput, FieldsConfig, FieldsConfigInput, SlotField, } from './ui/fields/Fields.vue.js';
|
|
5
6
|
export type { FieldsInstance } from './fields-instance.js';
|
|
7
|
+
export type { FieldsSlotProps } from './ui/fields/slot-props.js';
|
|
6
8
|
declare const _default: typeof __VLS_export;
|
|
7
9
|
export default _default;
|
|
8
10
|
declare const __VLS_export: __VLS_WithSlots<import("vue").DefineComponent<{
|
|
@@ -259,11 +261,7 @@ declare const __VLS_export: __VLS_WithSlots<import("vue").DefineComponent<{
|
|
|
259
261
|
style?: string | undefined;
|
|
260
262
|
}>) => any) | undefined;
|
|
261
263
|
"onInitial-value-ready"?: (() => any) | undefined;
|
|
262
|
-
}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>,
|
|
263
|
-
[x: string]: ((props: {
|
|
264
|
-
style: import("vue").CSSProperties;
|
|
265
|
-
}) => any) | undefined;
|
|
266
|
-
}>;
|
|
264
|
+
}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>, Record<string, (_props?: FieldsSlotProps) => unknown>>;
|
|
267
265
|
type __VLS_WithSlots<T, S> = T & {
|
|
268
266
|
new (): {
|
|
269
267
|
$slots: S;
|
|
@@ -11,6 +11,7 @@ const props = defineProps({
|
|
|
11
11
|
config: { type: null, required: false }
|
|
12
12
|
});
|
|
13
13
|
const emit = defineEmits(["update:config", "initial-value-ready"]);
|
|
14
|
+
const slots = defineSlots();
|
|
14
15
|
const modelValue = defineModel("modelValue", { type: Object, ...{
|
|
15
16
|
default: () => ({})
|
|
16
17
|
} });
|
|
@@ -83,7 +84,7 @@ export {
|
|
|
83
84
|
@initial-value-ready="handleInitialValueReady"
|
|
84
85
|
>
|
|
85
86
|
<template
|
|
86
|
-
v-for="(_, slotName) in
|
|
87
|
+
v-for="(_, slotName) in slots"
|
|
87
88
|
#[slotName]="slotProps"
|
|
88
89
|
>
|
|
89
90
|
<slot
|
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
import { Effect } from 'effect';
|
|
2
2
|
import { type FieldsConfigInput } from './ui/fields/Fields.vue.js';
|
|
3
|
+
import type { FieldsSlotProps } from './ui/fields/slot-props.js';
|
|
3
4
|
export { CalendarFieldC, EmptyFieldC, FieldC, FieldsBodyC, FieldsBodyInputC, FieldsConfigC, FieldsConfigInputC, NumberFieldC, SelectFieldC, SlotFieldC, StringFieldC, CURRENT_COMPATIBILITY_DATE, KIND, SUPPORTED_COMPATIBILITY_DATES, createFieldsConfig, } from './ui/fields/Fields.vue.js';
|
|
4
5
|
export type { EmptyField, Field, FieldsBody, FieldsBodyInput, FieldsConfig, FieldsConfigInput, SlotField, } from './ui/fields/Fields.vue.js';
|
|
5
6
|
export type { FieldsInstance } from './fields-instance.js';
|
|
7
|
+
export type { FieldsSlotProps } from './ui/fields/slot-props.js';
|
|
6
8
|
declare const _default: typeof __VLS_export;
|
|
7
9
|
export default _default;
|
|
8
10
|
declare const __VLS_export: __VLS_WithSlots<import("vue").DefineComponent<{
|
|
@@ -259,11 +261,7 @@ declare const __VLS_export: __VLS_WithSlots<import("vue").DefineComponent<{
|
|
|
259
261
|
style?: string | undefined;
|
|
260
262
|
}>) => any) | undefined;
|
|
261
263
|
"onInitial-value-ready"?: (() => any) | undefined;
|
|
262
|
-
}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>,
|
|
263
|
-
[x: string]: ((props: {
|
|
264
|
-
style: import("vue").CSSProperties;
|
|
265
|
-
}) => any) | undefined;
|
|
266
|
-
}>;
|
|
264
|
+
}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>, Record<string, (_props?: FieldsSlotProps) => unknown>>;
|
|
267
265
|
type __VLS_WithSlots<T, S> = T & {
|
|
268
266
|
new (): {
|
|
269
267
|
$slots: S;
|
|
@@ -234,6 +234,9 @@ function normalizeOptionalString(value) {
|
|
|
234
234
|
function getGeneralErrorKey(field) {
|
|
235
235
|
return `general.${field}`;
|
|
236
236
|
}
|
|
237
|
+
function getNodeErrorKey(itemId, field) {
|
|
238
|
+
return `${itemId}.${field}`;
|
|
239
|
+
}
|
|
237
240
|
function clearError(key) {
|
|
238
241
|
const nextErrors = {};
|
|
239
242
|
for (const [errorKey, errorValue] of Object.entries(validationErrors.value)) {
|
|
@@ -243,6 +246,18 @@ function clearError(key) {
|
|
|
243
246
|
}
|
|
244
247
|
validationErrors.value = nextErrors;
|
|
245
248
|
}
|
|
249
|
+
function clearNodeError(itemId, field) {
|
|
250
|
+
clearError(getNodeErrorKey(itemId, field));
|
|
251
|
+
}
|
|
252
|
+
function clearNodeErrors(itemId) {
|
|
253
|
+
const nextErrors = {};
|
|
254
|
+
for (const [errorKey, errorValue] of Object.entries(validationErrors.value)) {
|
|
255
|
+
if (!errorKey.startsWith(`${itemId}.`)) {
|
|
256
|
+
Reflect.set(nextErrors, errorKey, errorValue);
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
validationErrors.value = nextErrors;
|
|
260
|
+
}
|
|
246
261
|
function isCopyableNode(node) {
|
|
247
262
|
if (!node) {
|
|
248
263
|
return false;
|
|
@@ -300,6 +315,7 @@ function addDropdown() {
|
|
|
300
315
|
}
|
|
301
316
|
function deleteItem(itemId) {
|
|
302
317
|
draftTree.value = removeButtonConfiguratorSubtree(draftTree.value, itemId);
|
|
318
|
+
clearNodeErrors(itemId);
|
|
303
319
|
if (selectedItemId.value === itemId) {
|
|
304
320
|
selectedItemId.value = "general";
|
|
305
321
|
}
|
|
@@ -329,6 +345,22 @@ function updateSelectedTitle(value) {
|
|
|
329
345
|
};
|
|
330
346
|
});
|
|
331
347
|
}
|
|
348
|
+
function updateSelectedNodeId(value) {
|
|
349
|
+
const node = selectedNode.value;
|
|
350
|
+
if (!node || !isCopyableNode(node)) {
|
|
351
|
+
return;
|
|
352
|
+
}
|
|
353
|
+
clearNodeError(node.itemId, "id");
|
|
354
|
+
draftTree.value = updateButtonConfiguratorNode(draftTree.value, node.itemId, (item) => {
|
|
355
|
+
if (item.type === "group") {
|
|
356
|
+
return item;
|
|
357
|
+
}
|
|
358
|
+
return {
|
|
359
|
+
...item,
|
|
360
|
+
id: String(value).trim()
|
|
361
|
+
};
|
|
362
|
+
});
|
|
363
|
+
}
|
|
332
364
|
function updateSelectedTooltip(value) {
|
|
333
365
|
const node = selectedNode.value;
|
|
334
366
|
if (!node || node.item.type !== "button") {
|
|
@@ -486,6 +518,41 @@ function showImportErrorWithCopyAction(message, onClick) {
|
|
|
486
518
|
}
|
|
487
519
|
});
|
|
488
520
|
}
|
|
521
|
+
function validateEditableNodeIds() {
|
|
522
|
+
const errors = {};
|
|
523
|
+
const idOwners = {};
|
|
524
|
+
let firstInvalidItemId;
|
|
525
|
+
for (const node of draftTree.value.nodes) {
|
|
526
|
+
if (!isCopyableNode(node)) {
|
|
527
|
+
continue;
|
|
528
|
+
}
|
|
529
|
+
const idResult = z.uuid().safeParse(node.item.id);
|
|
530
|
+
if (!idResult.success) {
|
|
531
|
+
errors[getNodeErrorKey(node.itemId, "id")] = t("button-id-invalid");
|
|
532
|
+
firstInvalidItemId = firstInvalidItemId ?? node.itemId;
|
|
533
|
+
continue;
|
|
534
|
+
}
|
|
535
|
+
const existingIdOwner = idOwners[node.item.id];
|
|
536
|
+
if (existingIdOwner !== void 0) {
|
|
537
|
+
errors[getNodeErrorKey(node.itemId, "id")] = t("button-id-duplicate");
|
|
538
|
+
errors[getNodeErrorKey(existingIdOwner, "id")] = t("button-id-duplicate");
|
|
539
|
+
firstInvalidItemId = firstInvalidItemId ?? node.itemId;
|
|
540
|
+
continue;
|
|
541
|
+
}
|
|
542
|
+
idOwners[node.item.id] = node.itemId;
|
|
543
|
+
}
|
|
544
|
+
if (Object.keys(errors).length === 0) {
|
|
545
|
+
return true;
|
|
546
|
+
}
|
|
547
|
+
validationErrors.value = {
|
|
548
|
+
...validationErrors.value,
|
|
549
|
+
...errors
|
|
550
|
+
};
|
|
551
|
+
if (firstInvalidItemId) {
|
|
552
|
+
selectedItemId.value = firstInvalidItemId;
|
|
553
|
+
}
|
|
554
|
+
return false;
|
|
555
|
+
}
|
|
489
556
|
function buildDraftConfig() {
|
|
490
557
|
const generalStyleResult = ButtonsStyleC.safeParse(draftStyle.value);
|
|
491
558
|
if (!generalStyleResult.success) {
|
|
@@ -496,6 +563,9 @@ function buildDraftConfig() {
|
|
|
496
563
|
selectedItemId.value = "general";
|
|
497
564
|
return;
|
|
498
565
|
}
|
|
566
|
+
if (!validateEditableNodeIds()) {
|
|
567
|
+
return;
|
|
568
|
+
}
|
|
499
569
|
const bodyResult = ButtonBodyC.safeParse({
|
|
500
570
|
gap: draftGap.value,
|
|
501
571
|
style: generalStyleResult.data,
|
|
@@ -535,7 +605,8 @@ function buildAiPromptHeaderMarkdown() {
|
|
|
535
605
|
function buildMarkdownNotes() {
|
|
536
606
|
return [
|
|
537
607
|
"## \u6CE8\u610F\u4E8B\u9879",
|
|
538
|
-
"- \
|
|
608
|
+
"- \u5148\u5728\u4EE3\u7801\u91CC\u751F\u6210\u5E76\u4F7F\u7528 UUID\uFF0C\u518D\u628A\u540C\u4E00\u4E2A `id` \u7C98\u8D34\u5230\u6309\u94AE\u914D\u7F6E\u4E2D\u3002",
|
|
609
|
+
"- \u6309\u94AE\u548C\u4E0B\u62C9\u6309\u94AE\u7684 `id` \u90FD\u5FC5\u987B\u552F\u4E00\u4E14\u7B26\u5408 UUID \u683C\u5F0F\u3002",
|
|
539
610
|
"- `groups` \u662F\u6839\u7EA7\u6309\u94AE\u7EC4\u5217\u8868\uFF1B\u4E0B\u62C9\u6309\u94AE\u53EA\u80FD\u5B58\u5728\u4E8E\u6309\u94AE\u7EC4\u5185\u3002",
|
|
540
611
|
"- \u4E0B\u62C9\u6309\u94AE\u7684 `items` \u53EA\u80FD\u662F\u6309\u94AE\u5217\u8868\uFF0C\u4E0D\u80FD\u518D\u5D4C\u5957\u4E0B\u62C9\u6309\u94AE\u6216\u6309\u94AE\u7EC4\u3002",
|
|
541
612
|
"- `style` \u5FC5\u987B\u662F\u8FD4\u56DE\u6837\u5F0F\u5BF9\u8C61\u7684 CEL \u8868\u8FBE\u5F0F\u5B57\u7B26\u4E32\uFF1B\u5982\u679C\u4E0D\u80FD\u786E\u5B9A\u4E0A\u4E0B\u6587\u53D8\u91CF\uFF0C\u8BF7\u5148\u8BF4\u660E\u9650\u5236\u3002"
|
|
@@ -623,7 +694,7 @@ function buildPasteConfigErrorMarkdown(source, error) {
|
|
|
623
694
|
"",
|
|
624
695
|
"## \u5F53\u524D\u4EFB\u52A1",
|
|
625
696
|
"\u7528\u6237\u628A\u4E00\u6BB5\u914D\u7F6E\u7C98\u8D34\u56DE\u6309\u94AE\u914D\u7F6E\u5668\u65F6\u5931\u8D25\u4E86\u3002\u8BF7\u57FA\u4E8E\u4E0B\u9762\u7684\u539F\u59CB\u5185\u5BB9\u548C\u62A5\u9519\u4FEE\u590D\u5F53\u524D\u914D\u7F6E\u3002",
|
|
626
|
-
"\u8BF7\u4F18\u5148\u4FEE\u590D\u6700\u5C0F\u5FC5\u8981\u8303\u56F4\
|
|
697
|
+
"\u8BF7\u4F18\u5148\u4FEE\u590D\u6700\u5C0F\u5FC5\u8981\u8303\u56F4\u3002\u4EE3\u7801\u91CC\u7684 UUID \u5E94\u89C6\u4E3A\u6765\u6E90\uFF0C\u4E0D\u8981\u65E0\u610F\u4E49\u5730\u91CD\u5EFA\u73B0\u6709\u9879\u3002",
|
|
627
698
|
"\u53EA\u6709\u5F53\u7528\u6237\u660E\u786E\u8981\u6C42\u8F93\u51FA\u914D\u7F6E\u65F6\uFF0C\u624D\u8FD4\u56DE\u5B8C\u6574\u914D\u7F6E\uFF1B\u5982\u679C\u8FD4\u56DE\u914D\u7F6E\uFF0C\u5FC5\u987B\u653E\u5728 Markdown code block \u4E2D\u3002",
|
|
628
699
|
"",
|
|
629
700
|
buildPasteConfigErrorDetails(source, error),
|
|
@@ -830,6 +901,14 @@ function confirmChanges() {
|
|
|
830
901
|
{{ selectedItemId === "general" ? t("general-description") : t("detail-description") }}
|
|
831
902
|
</p>
|
|
832
903
|
|
|
904
|
+
<p
|
|
905
|
+
v-if="selectedNode && validationErrors[getNodeErrorKey(selectedNode.itemId, 'id')]"
|
|
906
|
+
data-slot="button-configurator-id-error"
|
|
907
|
+
class="mt-4 text-xs text-red-500"
|
|
908
|
+
>
|
|
909
|
+
{{ validationErrors[getNodeErrorKey(selectedItemId, "id")] }}
|
|
910
|
+
</p>
|
|
911
|
+
|
|
833
912
|
<div class="mt-6 flex flex-wrap gap-2">
|
|
834
913
|
<Button
|
|
835
914
|
v-if="canAddGroup"
|
|
@@ -912,6 +991,18 @@ function confirmChanges() {
|
|
|
912
991
|
data-slot="button-configurator-button"
|
|
913
992
|
class="mt-6 grid gap-4"
|
|
914
993
|
>
|
|
994
|
+
<label class="flex flex-col gap-2">
|
|
995
|
+
<span class="text-xs font-medium text-zinc-500">{{ t("button-id") }}</span>
|
|
996
|
+
<Input
|
|
997
|
+
data-slot="button-configurator-button-id"
|
|
998
|
+
:model-value="selectedButton.id"
|
|
999
|
+
:aria-invalid="validationErrors[getNodeErrorKey(selectedItemId, 'id')] ? 'true' : void 0"
|
|
1000
|
+
:placeholder="t('button-id-placeholder')"
|
|
1001
|
+
class="font-mono text-sm"
|
|
1002
|
+
@update:model-value="updateSelectedNodeId"
|
|
1003
|
+
/>
|
|
1004
|
+
</label>
|
|
1005
|
+
|
|
915
1006
|
<label class="flex flex-col gap-2">
|
|
916
1007
|
<span class="text-xs font-medium text-zinc-500">{{ t("button-title") }}</span>
|
|
917
1008
|
<Locale
|
|
@@ -999,6 +1090,18 @@ function confirmChanges() {
|
|
|
999
1090
|
data-slot="button-configurator-dropdown"
|
|
1000
1091
|
class="mt-6 grid gap-4"
|
|
1001
1092
|
>
|
|
1093
|
+
<label class="flex flex-col gap-2">
|
|
1094
|
+
<span class="text-xs font-medium text-zinc-500">{{ t("dropdown-id") }}</span>
|
|
1095
|
+
<Input
|
|
1096
|
+
data-slot="button-configurator-dropdown-id"
|
|
1097
|
+
:model-value="selectedDropdown.id"
|
|
1098
|
+
:aria-invalid="validationErrors[getNodeErrorKey(selectedItemId, 'id')] ? 'true' : void 0"
|
|
1099
|
+
:placeholder="t('button-id-placeholder')"
|
|
1100
|
+
class="font-mono text-sm"
|
|
1101
|
+
@update:model-value="updateSelectedNodeId"
|
|
1102
|
+
/>
|
|
1103
|
+
</label>
|
|
1104
|
+
|
|
1002
1105
|
<label class="flex flex-col gap-2">
|
|
1003
1106
|
<span class="text-xs font-medium text-zinc-500">{{ t("dropdown-title") }}</span>
|
|
1004
1107
|
<Locale
|
|
@@ -1155,7 +1258,7 @@ function confirmChanges() {
|
|
|
1155
1258
|
"copy-config-failed": "复制配置失败,请先修正当前配置中的错误。",
|
|
1156
1259
|
"general": "总览",
|
|
1157
1260
|
"general-description": "在这里管理按钮组和按钮组之间的间距。",
|
|
1158
|
-
"detail-description": "
|
|
1261
|
+
"detail-description": "先在代码里准备好 UUID / Effect,再把 UUID 粘贴到这里继续配置。",
|
|
1159
1262
|
"search": "搜索按钮",
|
|
1160
1263
|
"no-matches": "没有匹配的按钮。",
|
|
1161
1264
|
"group-label": "按钮组",
|
|
@@ -1171,6 +1274,11 @@ function confirmChanges() {
|
|
|
1171
1274
|
"general-style": "通用样式表达式",
|
|
1172
1275
|
"general-style-placeholder": "例如返回一个 style map,例如 display: flex",
|
|
1173
1276
|
"general-style-invalid": "样式表达式无效",
|
|
1277
|
+
"button-id": "按钮 ID",
|
|
1278
|
+
"dropdown-id": "下拉 ID",
|
|
1279
|
+
"button-id-placeholder": "粘贴代码里已经生成的 UUID",
|
|
1280
|
+
"button-id-invalid": "按钮 ID 必须是合法的 UUID",
|
|
1281
|
+
"button-id-duplicate": "按钮 ID 不能重复",
|
|
1174
1282
|
"button-title": "按钮名称",
|
|
1175
1283
|
"tooltip": "提示",
|
|
1176
1284
|
"button-icon": "按钮图标",
|
|
@@ -1207,7 +1315,7 @@ function confirmChanges() {
|
|
|
1207
1315
|
"copy-config-failed": "Failed to copy the config. Fix the current config errors first.",
|
|
1208
1316
|
"general": "General",
|
|
1209
1317
|
"general-description": "Manage button groups and the gap between them.",
|
|
1210
|
-
"detail-description": "
|
|
1318
|
+
"detail-description": "Prepare the UUID or effect in code first, then paste the UUID here to continue configuring.",
|
|
1211
1319
|
"search": "Search buttons",
|
|
1212
1320
|
"no-matches": "No matching buttons.",
|
|
1213
1321
|
"group-label": "Group",
|
|
@@ -1223,6 +1331,11 @@ function confirmChanges() {
|
|
|
1223
1331
|
"general-style": "Shared style expression",
|
|
1224
1332
|
"general-style-placeholder": "Return a style map, for example display: flex",
|
|
1225
1333
|
"general-style-invalid": "The style expression is invalid",
|
|
1334
|
+
"button-id": "Button ID",
|
|
1335
|
+
"dropdown-id": "Dropdown ID",
|
|
1336
|
+
"button-id-placeholder": "Paste the UUID generated in code",
|
|
1337
|
+
"button-id-invalid": "Button ID must be a valid UUID",
|
|
1338
|
+
"button-id-duplicate": "Button ID must be unique",
|
|
1226
1339
|
"button-title": "Button title",
|
|
1227
1340
|
"tooltip": "Tooltip",
|
|
1228
1341
|
"button-icon": "Button icon",
|
|
@@ -1259,7 +1372,7 @@ function confirmChanges() {
|
|
|
1259
1372
|
"copy-config-failed": "設定のコピーに失敗しました。現在の設定エラーを先に修正してください。",
|
|
1260
1373
|
"general": "全体",
|
|
1261
1374
|
"general-description": "ボタングループとその間隔を管理します。",
|
|
1262
|
-
"detail-description": "
|
|
1375
|
+
"detail-description": "先にコード側で UUID / Effect を準備し、その UUID をここへ貼り付けて設定を続けます。",
|
|
1263
1376
|
"search": "ボタンを検索",
|
|
1264
1377
|
"no-matches": "一致するボタンがありません。",
|
|
1265
1378
|
"group-label": "グループ",
|
|
@@ -1275,6 +1388,11 @@ function confirmChanges() {
|
|
|
1275
1388
|
"general-style": "共通スタイル式",
|
|
1276
1389
|
"general-style-placeholder": "例: style map を返す式。例: display: flex",
|
|
1277
1390
|
"general-style-invalid": "スタイル式が無効です",
|
|
1391
|
+
"button-id": "ボタン ID",
|
|
1392
|
+
"dropdown-id": "ドロップダウン ID",
|
|
1393
|
+
"button-id-placeholder": "コードで生成した UUID を貼り付け",
|
|
1394
|
+
"button-id-invalid": "ボタン ID は有効な UUID である必要があります",
|
|
1395
|
+
"button-id-duplicate": "ボタン ID は重複できません",
|
|
1278
1396
|
"button-title": "ボタン名",
|
|
1279
1397
|
"tooltip": "ツールチップ",
|
|
1280
1398
|
"button-icon": "ボタンアイコン",
|
|
@@ -1311,7 +1429,7 @@ function confirmChanges() {
|
|
|
1311
1429
|
"copy-config-failed": "설정 복사에 실패했습니다. 먼저 현재 설정 오류를 수정해 주세요.",
|
|
1312
1430
|
"general": "전체",
|
|
1313
1431
|
"general-description": "버튼 그룹과 그룹 간 간격을 관리합니다.",
|
|
1314
|
-
"detail-description": "
|
|
1432
|
+
"detail-description": "먼저 코드에서 UUID / Effect 를 준비한 뒤, 같은 UUID 를 여기 붙여 넣어 설정을 이어갑니다.",
|
|
1315
1433
|
"search": "버튼 검색",
|
|
1316
1434
|
"no-matches": "일치하는 버튼이 없습니다.",
|
|
1317
1435
|
"group-label": "그룹",
|
|
@@ -1327,6 +1445,11 @@ function confirmChanges() {
|
|
|
1327
1445
|
"general-style": "공통 스타일 식",
|
|
1328
1446
|
"general-style-placeholder": "예: style map 을 반환하는 식. 예: display: flex",
|
|
1329
1447
|
"general-style-invalid": "스타일 식이 올바르지 않습니다",
|
|
1448
|
+
"button-id": "버튼 ID",
|
|
1449
|
+
"dropdown-id": "드롭다운 ID",
|
|
1450
|
+
"button-id-placeholder": "코드에서 생성한 UUID 붙여 넣기",
|
|
1451
|
+
"button-id-invalid": "버튼 ID 는 올바른 UUID 여야 합니다",
|
|
1452
|
+
"button-id-duplicate": "버튼 ID 는 중복될 수 없습니다",
|
|
1330
1453
|
"button-title": "버튼 이름",
|
|
1331
1454
|
"tooltip": "툴팁",
|
|
1332
1455
|
"button-icon": "버튼 아이콘",
|
|
@@ -3,6 +3,7 @@ import type { CSSProperties } from 'vue';
|
|
|
3
3
|
export { CalendarFieldC, CURRENT_COMPATIBILITY_DATE, EmptyFieldC, FieldC, FieldsBodyC, FieldsBodyInputC, FieldsConfigC, FieldsConfigInputC, KIND, NumberFieldC, SelectFieldC, SlotFieldC, SUPPORTED_COMPATIBILITY_DATES, StringFieldC, ValidationRuleC, createFieldsConfig, validationC, } from './schema.js';
|
|
4
4
|
export type { EmptyField, Field, FieldsBody, FieldsBodyInput, FieldsConfig, FieldsConfigInput, SlotField, ValidationRule, } from './schema.js';
|
|
5
5
|
export type { FieldsInstance } from '../../fields-instance.js';
|
|
6
|
+
export type { FieldsSlotProps } from './slot-props.js';
|
|
6
7
|
declare const _default: typeof __VLS_export;
|
|
7
8
|
export default _default;
|
|
8
9
|
declare const __VLS_export: __VLS_WithSlots<import("vue").DefineComponent<{
|
|
@@ -499,13 +500,11 @@ declare const __VLS_export: __VLS_WithSlots<import("vue").DefineComponent<{
|
|
|
499
500
|
style?: string | undefined;
|
|
500
501
|
}>) => any) | undefined;
|
|
501
502
|
"onInitial-value-ready"?: (() => any) | undefined;
|
|
502
|
-
}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>, {
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
}
|
|
507
|
-
default?: (props: {}) => any;
|
|
508
|
-
}>;
|
|
503
|
+
}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>, Record<string, (_props?: Readonly<{
|
|
504
|
+
style: CSSProperties;
|
|
505
|
+
valid: Effect.Effect<boolean, never>;
|
|
506
|
+
form: Readonly<Record<string, unknown>>;
|
|
507
|
+
}>) => unknown>>;
|
|
509
508
|
type __VLS_WithSlots<T, S> = T & {
|
|
510
509
|
new (): {
|
|
511
510
|
$slots: S;
|
|
@@ -7,7 +7,7 @@ import { Icon } from "@iconify/vue";
|
|
|
7
7
|
import { Effect } from "effect";
|
|
8
8
|
import { format, parse } from "date-fns";
|
|
9
9
|
import { deleteProperty, getProperty, hasProperty, setProperty } from "dot-prop";
|
|
10
|
-
import { nextTick, ref, toRaw, useId, watch, watchEffect } from "vue";
|
|
10
|
+
import { computed, nextTick, readonly, ref, toRaw, useId, watch, watchEffect } from "vue";
|
|
11
11
|
import { useI18n } from "vue-i18n";
|
|
12
12
|
import { useCheating } from "#imports";
|
|
13
13
|
import { Calendar } from "../calendar";
|
|
@@ -28,6 +28,7 @@ const defaultConfig = createFieldsConfig({
|
|
|
28
28
|
const props = defineProps({
|
|
29
29
|
config: { type: null, required: true }
|
|
30
30
|
});
|
|
31
|
+
defineSlots();
|
|
31
32
|
const emit = defineEmits(["update:config", "initial-value-ready"]);
|
|
32
33
|
const config = computedAsync(async () => FieldsConfigC.parse(await props.config.pipe(Effect.runPromise) ?? defaultConfig));
|
|
33
34
|
const { t, locale } = useI18n();
|
|
@@ -318,12 +319,14 @@ function handleConfiguratorConfirm(nextConfig) {
|
|
|
318
319
|
displayConfig.value = cloneConfig(nextConfig);
|
|
319
320
|
emit("update:config", nextConfig);
|
|
320
321
|
}
|
|
322
|
+
const valid = Effect.async((resume) => {
|
|
323
|
+
void waitForReady().then(() => {
|
|
324
|
+
resume(Effect.sync(() => validateFields()));
|
|
325
|
+
});
|
|
326
|
+
});
|
|
327
|
+
const slotForm = computed(() => readonly(modelValue.value));
|
|
321
328
|
const fieldsApi = {
|
|
322
|
-
valid
|
|
323
|
-
void waitForReady().then(() => {
|
|
324
|
-
resume(Effect.sync(() => validateFields()));
|
|
325
|
-
});
|
|
326
|
-
})
|
|
329
|
+
valid
|
|
327
330
|
};
|
|
328
331
|
defineExpose(fieldsApi);
|
|
329
332
|
watch(config, (value) => {
|
|
@@ -427,7 +430,9 @@ export {
|
|
|
427
430
|
<slot
|
|
428
431
|
v-if="field.type === 'slot'"
|
|
429
432
|
:name="field.id"
|
|
433
|
+
:form="slotForm"
|
|
430
434
|
:style="getFieldStyle(field)"
|
|
435
|
+
:valid="valid"
|
|
431
436
|
/>
|
|
432
437
|
<div
|
|
433
438
|
v-else-if="field.type === 'empty'"
|
|
@@ -3,6 +3,7 @@ import type { CSSProperties } from 'vue';
|
|
|
3
3
|
export { CalendarFieldC, CURRENT_COMPATIBILITY_DATE, EmptyFieldC, FieldC, FieldsBodyC, FieldsBodyInputC, FieldsConfigC, FieldsConfigInputC, KIND, NumberFieldC, SelectFieldC, SlotFieldC, SUPPORTED_COMPATIBILITY_DATES, StringFieldC, ValidationRuleC, createFieldsConfig, validationC, } from './schema.js';
|
|
4
4
|
export type { EmptyField, Field, FieldsBody, FieldsBodyInput, FieldsConfig, FieldsConfigInput, SlotField, ValidationRule, } from './schema.js';
|
|
5
5
|
export type { FieldsInstance } from '../../fields-instance.js';
|
|
6
|
+
export type { FieldsSlotProps } from './slot-props.js';
|
|
6
7
|
declare const _default: typeof __VLS_export;
|
|
7
8
|
export default _default;
|
|
8
9
|
declare const __VLS_export: __VLS_WithSlots<import("vue").DefineComponent<{
|
|
@@ -499,13 +500,11 @@ declare const __VLS_export: __VLS_WithSlots<import("vue").DefineComponent<{
|
|
|
499
500
|
style?: string | undefined;
|
|
500
501
|
}>) => any) | undefined;
|
|
501
502
|
"onInitial-value-ready"?: (() => any) | undefined;
|
|
502
|
-
}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>, {
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
}
|
|
507
|
-
default?: (props: {}) => any;
|
|
508
|
-
}>;
|
|
503
|
+
}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>, Record<string, (_props?: Readonly<{
|
|
504
|
+
style: CSSProperties;
|
|
505
|
+
valid: Effect.Effect<boolean, never>;
|
|
506
|
+
form: Readonly<Record<string, unknown>>;
|
|
507
|
+
}>) => unknown>>;
|
|
509
508
|
type __VLS_WithSlots<T, S> = T & {
|
|
510
509
|
new (): {
|
|
511
510
|
$slots: S;
|
|
File without changes
|
|
@@ -489,6 +489,17 @@ function updateSelectedFieldTitle(value) {
|
|
|
489
489
|
title: value
|
|
490
490
|
}));
|
|
491
491
|
}
|
|
492
|
+
function updateSelectedFieldId(value) {
|
|
493
|
+
const selected = selectedField.value;
|
|
494
|
+
if (!selected || selected.field.type !== "slot") {
|
|
495
|
+
return;
|
|
496
|
+
}
|
|
497
|
+
clearFieldError(selected.draftId, "id");
|
|
498
|
+
updateDraftField(selected.draftId, (field) => field.type === "slot" ? {
|
|
499
|
+
...field,
|
|
500
|
+
id: String(value).trim()
|
|
501
|
+
} : field);
|
|
502
|
+
}
|
|
492
503
|
async function copySelectedFieldId() {
|
|
493
504
|
const selected = selectedField.value;
|
|
494
505
|
if (!selected) {
|
|
@@ -932,6 +943,12 @@ function getSchemaIssues(field) {
|
|
|
932
943
|
}
|
|
933
944
|
}
|
|
934
945
|
}
|
|
946
|
+
function getSchemaIssueMessage(issue, path) {
|
|
947
|
+
if (path[0] === "id") {
|
|
948
|
+
return t("field-id-invalid");
|
|
949
|
+
}
|
|
950
|
+
return issue.message;
|
|
951
|
+
}
|
|
935
952
|
function normalizeIssuePath(path) {
|
|
936
953
|
const normalizedPath = [];
|
|
937
954
|
for (const segment of path) {
|
|
@@ -987,11 +1004,12 @@ function validateDraftFields() {
|
|
|
987
1004
|
firstInvalidItemId = firstInvalidItemId ?? item.draftId;
|
|
988
1005
|
}
|
|
989
1006
|
for (const issue of getSchemaIssues(item.field)) {
|
|
990
|
-
const
|
|
1007
|
+
const issuePath = normalizeIssuePath(issue.path);
|
|
1008
|
+
const issueKey = getIssueErrorKey(item.draftId, issuePath);
|
|
991
1009
|
if (!issueKey) {
|
|
992
1010
|
continue;
|
|
993
1011
|
}
|
|
994
|
-
setError(errors, issueKey, issue
|
|
1012
|
+
setError(errors, issueKey, getSchemaIssueMessage(issue, issuePath));
|
|
995
1013
|
firstInvalidItemId = firstInvalidItemId ?? item.draftId;
|
|
996
1014
|
}
|
|
997
1015
|
}
|
|
@@ -1091,7 +1109,8 @@ function buildDslGuideMarkdown() {
|
|
|
1091
1109
|
"- `select.options` \u901A\u5E38\u8FD4\u56DE\u5217\u8868\uFF1B`label` / `value` / `key` \u7528\u6765\u63CF\u8FF0\u5355\u4E2A\u9009\u9879\u5982\u4F55\u6620\u5C04\u3002",
|
|
1092
1110
|
"",
|
|
1093
1111
|
"### 3. \u5B57\u6BB5\u7C7B\u578B\u7EA6\u675F",
|
|
1094
|
-
"- \
|
|
1112
|
+
"- \u4EE3\u7801\u91CC\u5E94\u5148\u751F\u6210\u5E76\u4F7F\u7528 UUID\uFF0C\u518D\u628A\u540C\u4E00\u4E2A `id` \u7C98\u8D34\u56DE\u5B57\u6BB5\u914D\u7F6E\u3002",
|
|
1113
|
+
"- \u6240\u6709\u5B57\u6BB5\u90FD\u5FC5\u987B\u5305\u542B\u552F\u4E00\u4E14\u5408\u6CD5\u7684 UUID `id`\u3002",
|
|
1095
1114
|
"- \u53EA\u6709\u975E `slot` / `empty` \u5B57\u6BB5\u53EF\u4EE5\u914D\u7F6E `path`\uFF0C\u5E76\u53C2\u4E0E\u8868\u5355\u503C\u8BFB\u5199\u3002",
|
|
1096
1115
|
"- `slot` \u548C `empty` \u5B57\u6BB5\u90FD\u4E0D\u4F1A\u7ED1\u5B9A\u6A21\u578B\u503C\uFF0C\u53EA\u5141\u8BB8 `id`\u3001`type` \u548C\u53EF\u9009\u7684 `style`\u3002"
|
|
1097
1116
|
].join("\n");
|
|
@@ -1099,7 +1118,8 @@ function buildDslGuideMarkdown() {
|
|
|
1099
1118
|
function buildMarkdownNotes() {
|
|
1100
1119
|
return [
|
|
1101
1120
|
"## \u6CE8\u610F\u4E8B\u9879",
|
|
1102
|
-
"- \
|
|
1121
|
+
"- \u5148\u5728\u4EE3\u7801\u91CC\u751F\u6210\u5E76\u4F7F\u7528 UUID\uFF0C\u518D\u628A\u540C\u4E00\u4E2A `id` \u7C98\u8D34\u5230\u5B57\u6BB5\u914D\u7F6E\u4E2D\u3002",
|
|
1122
|
+
"- \u6240\u6709\u5B57\u6BB5 `id` \u90FD\u5FC5\u987B\u552F\u4E00\u4E14\u7B26\u5408 UUID \u683C\u5F0F\u3002",
|
|
1103
1123
|
"- `slot` \u4E0E `empty` \u5B57\u6BB5\u53EA\u80FD\u4F7F\u7528 `id`\u3001`type` \u548C\u53EF\u9009\u7684 `style`\u3002",
|
|
1104
1124
|
"- \u975E `slot` / `empty` \u5B57\u6BB5\u7684 `path` \u5FC5\u987B\u552F\u4E00\u4E14\u4E0D\u80FD\u4E3A\u7A7A\u3002",
|
|
1105
1125
|
"- \u8868\u8FBE\u5F0F\u5B57\u6BB5\u5FC5\u987B\u4E25\u683C\u9075\u5B88 schema \u7EA6\u675F\uFF1B\u5982\u679C schema \u4E0D\u652F\u6301\uFF0C\u5C31\u76F4\u63A5\u8BF4\u660E\u9650\u5236\u3002"
|
|
@@ -1187,7 +1207,7 @@ function buildPasteConfigErrorMarkdown(source, error) {
|
|
|
1187
1207
|
"",
|
|
1188
1208
|
"## \u5F53\u524D\u4EFB\u52A1",
|
|
1189
1209
|
"\u7528\u6237\u628A\u4E00\u6BB5\u914D\u7F6E\u7C98\u8D34\u56DE\u5B57\u6BB5\u914D\u7F6E\u5668\u65F6\u5931\u8D25\u4E86\u3002\u8BF7\u57FA\u4E8E\u4E0B\u9762\u7684\u539F\u59CB\u5185\u5BB9\u548C\u62A5\u9519\u4FEE\u590D\u5F53\u524D\u914D\u7F6E\u3002",
|
|
1190
|
-
"\u8BF7\u4F18\u5148\u4FEE\u590D\u6700\u5C0F\u5FC5\u8981\u8303\u56F4\uFF0C\u4E0D\u8981\u53D1\u660E schema \u4E2D\u4E0D\u5B58\u5728\u7684\u5B57\u6BB5\uFF0C\
|
|
1210
|
+
"\u8BF7\u4F18\u5148\u4FEE\u590D\u6700\u5C0F\u5FC5\u8981\u8303\u56F4\uFF0C\u4E0D\u8981\u53D1\u660E schema \u4E2D\u4E0D\u5B58\u5728\u7684\u5B57\u6BB5\u3002\u4EE3\u7801\u91CC\u7684 UUID \u5E94\u89C6\u4E3A\u6765\u6E90\uFF0C\u4E0D\u8981\u65E0\u610F\u4E49\u5730\u91CD\u5EFA\u73B0\u6709\u5B57\u6BB5\u3002",
|
|
1191
1211
|
"\u53EA\u6709\u5F53\u7528\u6237\u660E\u786E\u8981\u6C42\u8F93\u51FA\u914D\u7F6E\u65F6\uFF0C\u624D\u8FD4\u56DE\u5B8C\u6574\u914D\u7F6E\uFF1B\u5982\u679C\u8FD4\u56DE\u914D\u7F6E\uFF0C\u5FC5\u987B\u653E\u5728 Markdown code block \u4E2D\u3002",
|
|
1192
1212
|
"",
|
|
1193
1213
|
buildPasteConfigErrorDetails(source, error),
|
|
@@ -1525,6 +1545,26 @@ function confirmChanges() {
|
|
|
1525
1545
|
{{ validationErrors[getFieldErrorKey(selectedField.draftId, "id")] }}
|
|
1526
1546
|
</p>
|
|
1527
1547
|
|
|
1548
|
+
<section
|
|
1549
|
+
v-if="selectedField.field.type === 'slot'"
|
|
1550
|
+
data-slot="fields-configurator-field-id-section"
|
|
1551
|
+
class="flex flex-col gap-2"
|
|
1552
|
+
>
|
|
1553
|
+
<label class="flex flex-col gap-2">
|
|
1554
|
+
<span class="text-xs font-medium text-zinc-500">
|
|
1555
|
+
{{ t("field-id") }}
|
|
1556
|
+
</span>
|
|
1557
|
+
<Input
|
|
1558
|
+
data-slot="fields-configurator-field-id-input"
|
|
1559
|
+
:model-value="selectedField.field.id"
|
|
1560
|
+
:aria-invalid="validationErrors[getFieldErrorKey(selectedField.draftId, 'id')] ? 'true' : void 0"
|
|
1561
|
+
:placeholder="t('field-id-placeholder')"
|
|
1562
|
+
class="font-mono text-sm"
|
|
1563
|
+
@update:model-value="updateSelectedFieldId"
|
|
1564
|
+
/>
|
|
1565
|
+
</label>
|
|
1566
|
+
</section>
|
|
1567
|
+
|
|
1528
1568
|
<section
|
|
1529
1569
|
v-if="!isPassiveField(selectedField.field)"
|
|
1530
1570
|
data-slot="fields-configurator-field-path-section"
|
|
@@ -2188,6 +2228,8 @@ function confirmChanges() {
|
|
|
2188
2228
|
"field-type-empty": "空白",
|
|
2189
2229
|
"field-type-slot": "插槽",
|
|
2190
2230
|
"field-id": "字段 ID",
|
|
2231
|
+
"field-id-placeholder": "粘贴代码里已经生成的 UUID",
|
|
2232
|
+
"field-id-invalid": "字段 ID 必须是合法的 UUID",
|
|
2191
2233
|
"field-id-duplicate": "字段 ID 不能重复",
|
|
2192
2234
|
"field-path": "字段路径",
|
|
2193
2235
|
"field-path-placeholder": "例如 profile.name",
|
|
@@ -2291,6 +2333,8 @@ function confirmChanges() {
|
|
|
2291
2333
|
"field-type-empty": "空白",
|
|
2292
2334
|
"field-type-slot": "スロット",
|
|
2293
2335
|
"field-id": "フィールド ID",
|
|
2336
|
+
"field-id-placeholder": "コードで生成した UUID を貼り付け",
|
|
2337
|
+
"field-id-invalid": "フィールド ID は有効な UUID である必要があります",
|
|
2294
2338
|
"field-id-duplicate": "フィールド ID は重複できません",
|
|
2295
2339
|
"field-path": "フィールドパス",
|
|
2296
2340
|
"field-path-placeholder": "例: profile.name",
|
|
@@ -2394,6 +2438,8 @@ function confirmChanges() {
|
|
|
2394
2438
|
"field-type-empty": "Empty",
|
|
2395
2439
|
"field-type-slot": "Slot",
|
|
2396
2440
|
"field-id": "Field ID",
|
|
2441
|
+
"field-id-placeholder": "Paste the UUID generated in code",
|
|
2442
|
+
"field-id-invalid": "Field ID must be a valid UUID",
|
|
2397
2443
|
"field-id-duplicate": "Field ID must be unique",
|
|
2398
2444
|
"field-path": "Field path",
|
|
2399
2445
|
"field-path-placeholder": "For example profile.name",
|
package/dist/types.d.mts
CHANGED
|
@@ -6,6 +6,8 @@ export type ModuleOptions = typeof Module extends NuxtModule<infer O> ? Partial<
|
|
|
6
6
|
|
|
7
7
|
export { type FieldsInstance } from '../dist/runtime/components/fields-instance.js'
|
|
8
8
|
|
|
9
|
+
export { type FieldsSlotProps } from '../dist/runtime/components/ui/fields/slot-props.js'
|
|
10
|
+
|
|
9
11
|
export { default } from './module.mjs'
|
|
10
12
|
|
|
11
13
|
export { type Env } from './module.mjs'
|