@konomi-app/ui 5.2.1 → 5.3.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/dist/index.cjs +886 -6
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +118 -2
- package/dist/index.d.ts +118 -2
- package/dist/index.js +886 -6
- package/dist/index.js.map +1 -1
- package/package.json +11 -4
package/dist/index.cjs
CHANGED
|
@@ -60,14 +60,168 @@ var createInitialState = () => ({
|
|
|
60
60
|
queues: [],
|
|
61
61
|
steps: [],
|
|
62
62
|
timer: null,
|
|
63
|
-
title: ""
|
|
63
|
+
title: "",
|
|
64
|
+
formFields: [],
|
|
65
|
+
formValues: {},
|
|
66
|
+
formErrors: {},
|
|
67
|
+
formTouched: {},
|
|
68
|
+
formLayout: {},
|
|
69
|
+
formValidateOnChange: true,
|
|
70
|
+
formValidateOnBlur: true,
|
|
71
|
+
stepFormSteps: [],
|
|
72
|
+
stepFormCurrentIndex: 0,
|
|
73
|
+
stepFormNextText: "\u6B21\u3078",
|
|
74
|
+
stepFormPrevText: "\u623B\u308B",
|
|
75
|
+
stepFormSubmitText: "OK"
|
|
64
76
|
});
|
|
65
77
|
|
|
78
|
+
// src/zod-utils.ts
|
|
79
|
+
function resolveTypeName(field) {
|
|
80
|
+
const raw = field._def.typeName ?? field._def.type;
|
|
81
|
+
if (!raw) return "";
|
|
82
|
+
const v4Map = {
|
|
83
|
+
string: "ZodString",
|
|
84
|
+
number: "ZodNumber",
|
|
85
|
+
boolean: "ZodBoolean",
|
|
86
|
+
enum: "ZodEnum",
|
|
87
|
+
date: "ZodDate",
|
|
88
|
+
optional: "ZodOptional",
|
|
89
|
+
nullable: "ZodNullable",
|
|
90
|
+
default: "ZodDefault",
|
|
91
|
+
object: "ZodObject",
|
|
92
|
+
pipe: "ZodPipe"
|
|
93
|
+
};
|
|
94
|
+
return v4Map[raw] ?? raw;
|
|
95
|
+
}
|
|
96
|
+
function unwrapType(zodType) {
|
|
97
|
+
let inner = zodType;
|
|
98
|
+
let required = true;
|
|
99
|
+
let defaultValue = void 0;
|
|
100
|
+
let description = zodType.description ?? "";
|
|
101
|
+
while (true) {
|
|
102
|
+
const typeName = resolveTypeName(inner);
|
|
103
|
+
if (typeName === "ZodOptional" || typeName === "ZodNullable") {
|
|
104
|
+
required = false;
|
|
105
|
+
inner = inner._def.innerType;
|
|
106
|
+
} else if (typeName === "ZodDefault") {
|
|
107
|
+
const raw = inner._def.defaultValue;
|
|
108
|
+
defaultValue = typeof raw === "function" ? raw() : raw;
|
|
109
|
+
inner = inner._def.innerType;
|
|
110
|
+
} else if (typeName === "ZodEffects") {
|
|
111
|
+
inner = inner._def.schema;
|
|
112
|
+
} else {
|
|
113
|
+
break;
|
|
114
|
+
}
|
|
115
|
+
if (!description && inner.description) {
|
|
116
|
+
description = inner.description;
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
return { inner, required, defaultValue, description };
|
|
120
|
+
}
|
|
121
|
+
function extractFieldMeta(key, zodType) {
|
|
122
|
+
const { inner, required, defaultValue, description } = unwrapType(zodType);
|
|
123
|
+
const typeName = resolveTypeName(inner);
|
|
124
|
+
let inputType;
|
|
125
|
+
let options = [];
|
|
126
|
+
let min;
|
|
127
|
+
let max;
|
|
128
|
+
let minLength;
|
|
129
|
+
let maxLength;
|
|
130
|
+
switch (typeName) {
|
|
131
|
+
case "ZodString": {
|
|
132
|
+
inputType = "text";
|
|
133
|
+
if (inner.format === "email") inputType = "email";
|
|
134
|
+
else if (inner.format === "url") inputType = "url";
|
|
135
|
+
if (inner.minLength != null) minLength = inner.minLength;
|
|
136
|
+
if (inner.maxLength != null) maxLength = inner.maxLength;
|
|
137
|
+
const checks = inner._def.checks ?? [];
|
|
138
|
+
for (const check of checks) {
|
|
139
|
+
const kind = check.kind ?? check.def?.check;
|
|
140
|
+
const fmt = check.format ?? check.def?.format;
|
|
141
|
+
if (!fmt && (kind === "email" || fmt === "email")) inputType = "email";
|
|
142
|
+
else if (!fmt && (kind === "url" || fmt === "url")) inputType = "url";
|
|
143
|
+
else if (fmt === "email" && inputType === "text") inputType = "email";
|
|
144
|
+
else if (fmt === "url" && inputType === "text") inputType = "url";
|
|
145
|
+
if (kind === "min" && check.value != null && minLength == null) minLength = check.value;
|
|
146
|
+
if (kind === "max" && check.value != null && maxLength == null) maxLength = check.value;
|
|
147
|
+
}
|
|
148
|
+
break;
|
|
149
|
+
}
|
|
150
|
+
case "ZodNumber": {
|
|
151
|
+
inputType = "number";
|
|
152
|
+
if (inner.minValue != null) min = inner.minValue;
|
|
153
|
+
if (inner.maxValue != null) max = inner.maxValue;
|
|
154
|
+
if (min == null || max == null) {
|
|
155
|
+
const checks = inner._def.checks ?? [];
|
|
156
|
+
for (const check of checks) {
|
|
157
|
+
if (check.kind === "min" && check.value != null && min == null) min = check.value;
|
|
158
|
+
if (check.kind === "max" && check.value != null && max == null) max = check.value;
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
break;
|
|
162
|
+
}
|
|
163
|
+
case "ZodBoolean":
|
|
164
|
+
inputType = "checkbox";
|
|
165
|
+
break;
|
|
166
|
+
case "ZodEnum": {
|
|
167
|
+
inputType = "select";
|
|
168
|
+
if (inner.options?.length) {
|
|
169
|
+
options = [...inner.options];
|
|
170
|
+
} else if (inner._def.entries) {
|
|
171
|
+
options = Object.values(inner._def.entries);
|
|
172
|
+
} else if (inner._def.values?.length) {
|
|
173
|
+
options = [...inner._def.values];
|
|
174
|
+
}
|
|
175
|
+
break;
|
|
176
|
+
}
|
|
177
|
+
case "ZodNativeEnum": {
|
|
178
|
+
inputType = "select";
|
|
179
|
+
const enumValues = inner._def.values;
|
|
180
|
+
if (enumValues) {
|
|
181
|
+
options = Object.values(enumValues).filter((v) => typeof v === "string");
|
|
182
|
+
}
|
|
183
|
+
break;
|
|
184
|
+
}
|
|
185
|
+
case "ZodDate":
|
|
186
|
+
inputType = "date";
|
|
187
|
+
break;
|
|
188
|
+
default:
|
|
189
|
+
return null;
|
|
190
|
+
}
|
|
191
|
+
const label = description || key;
|
|
192
|
+
return {
|
|
193
|
+
key,
|
|
194
|
+
inputType,
|
|
195
|
+
label,
|
|
196
|
+
description: description && description !== label ? description : "",
|
|
197
|
+
required,
|
|
198
|
+
options,
|
|
199
|
+
placeholder: "",
|
|
200
|
+
min,
|
|
201
|
+
max,
|
|
202
|
+
minLength,
|
|
203
|
+
maxLength,
|
|
204
|
+
defaultValue
|
|
205
|
+
};
|
|
206
|
+
}
|
|
207
|
+
function extractFormFields(schema) {
|
|
208
|
+
const shapeDef = schema._def.shape;
|
|
209
|
+
if (!shapeDef) return [];
|
|
210
|
+
const shape = typeof shapeDef === "function" ? shapeDef() : shapeDef;
|
|
211
|
+
if (!shape) return [];
|
|
212
|
+
const fields = [];
|
|
213
|
+
for (const [key, zodType] of Object.entries(shape)) {
|
|
214
|
+
const meta = extractFieldMeta(key, zodType);
|
|
215
|
+
if (meta) fields.push(meta);
|
|
216
|
+
}
|
|
217
|
+
return fields;
|
|
218
|
+
}
|
|
219
|
+
|
|
66
220
|
// src/controller.ts
|
|
67
221
|
function normalizeItemInput(input) {
|
|
68
222
|
return typeof input === "string" ? { key: input, label: input } : input;
|
|
69
223
|
}
|
|
70
|
-
var _state, _listeners, _resolver, _timerId, _DialogController_instances, emit_fn, update_fn, createPromise_fn, resolve_fn, clearTimer_fn, updateItemStatus_fn;
|
|
224
|
+
var _state, _listeners, _resolver, _timerId, _formSchema, _formResult, _stepFormSchemas, _stepFormResults, _DialogController_instances, emit_fn, update_fn, validateFormField_fn, updateCurrentStep_fn, validateStepField_fn, createPromise_fn, resolve_fn, clearTimer_fn, updateItemStatus_fn;
|
|
71
225
|
var DialogController = class {
|
|
72
226
|
constructor() {
|
|
73
227
|
__privateAdd(this, _DialogController_instances);
|
|
@@ -75,6 +229,10 @@ var DialogController = class {
|
|
|
75
229
|
__privateAdd(this, _listeners, /* @__PURE__ */ new Set());
|
|
76
230
|
__privateAdd(this, _resolver, null);
|
|
77
231
|
__privateAdd(this, _timerId, null);
|
|
232
|
+
__privateAdd(this, _formSchema, null);
|
|
233
|
+
__privateAdd(this, _formResult, null);
|
|
234
|
+
__privateAdd(this, _stepFormSchemas, []);
|
|
235
|
+
__privateAdd(this, _stepFormResults, {});
|
|
78
236
|
__privateSet(this, _state, createInitialState());
|
|
79
237
|
}
|
|
80
238
|
// ─── Observable ──────────────────────────────────────────
|
|
@@ -220,9 +378,202 @@ var DialogController = class {
|
|
|
220
378
|
clearSteps() {
|
|
221
379
|
__privateMethod(this, _DialogController_instances, update_fn).call(this, { steps: [] });
|
|
222
380
|
}
|
|
381
|
+
// ─── Form ─────────────────────────────────────────────────
|
|
382
|
+
form(schema, options) {
|
|
383
|
+
__privateMethod(this, _DialogController_instances, clearTimer_fn).call(this);
|
|
384
|
+
__privateSet(this, _formSchema, schema);
|
|
385
|
+
__privateSet(this, _formResult, null);
|
|
386
|
+
const fields = extractFormFields(schema);
|
|
387
|
+
const defaultValues = {};
|
|
388
|
+
for (const field of fields) {
|
|
389
|
+
if (field.defaultValue !== void 0) {
|
|
390
|
+
defaultValues[field.key] = field.defaultValue;
|
|
391
|
+
}
|
|
392
|
+
}
|
|
393
|
+
if (options?.defaultValues) {
|
|
394
|
+
Object.assign(defaultValues, options.defaultValues);
|
|
395
|
+
}
|
|
396
|
+
__privateMethod(this, _DialogController_instances, update_fn).call(this, {
|
|
397
|
+
open: true,
|
|
398
|
+
dialogType: "form",
|
|
399
|
+
title: options?.title ?? "",
|
|
400
|
+
label: "",
|
|
401
|
+
description: options?.description ?? "",
|
|
402
|
+
icon: null,
|
|
403
|
+
showConfirmButton: true,
|
|
404
|
+
showCancelButton: true,
|
|
405
|
+
confirmButtonText: options?.confirmButtonText ?? "OK",
|
|
406
|
+
cancelButtonText: options?.cancelButtonText ?? "\u30AD\u30E3\u30F3\u30BB\u30EB",
|
|
407
|
+
allowOutsideClick: options?.allowOutsideClick ?? false,
|
|
408
|
+
allowEscapeKey: options?.allowEscapeKey ?? true,
|
|
409
|
+
progress: null,
|
|
410
|
+
timer: null,
|
|
411
|
+
formFields: fields,
|
|
412
|
+
formValues: defaultValues,
|
|
413
|
+
formErrors: {},
|
|
414
|
+
formTouched: {},
|
|
415
|
+
formLayout: options?.layout ?? {},
|
|
416
|
+
formValidateOnChange: options?.validateOnChange ?? true,
|
|
417
|
+
formValidateOnBlur: options?.validateOnBlur ?? true
|
|
418
|
+
});
|
|
419
|
+
return __privateMethod(this, _DialogController_instances, createPromise_fn).call(this, null).then((r) => {
|
|
420
|
+
const data = __privateGet(this, _formResult);
|
|
421
|
+
__privateSet(this, _formSchema, null);
|
|
422
|
+
__privateSet(this, _formResult, null);
|
|
423
|
+
return r.isConfirmed ? data : null;
|
|
424
|
+
});
|
|
425
|
+
}
|
|
426
|
+
updateFormField(key, value) {
|
|
427
|
+
const formValues = { ...__privateGet(this, _state).formValues, [key]: value };
|
|
428
|
+
const formTouched = { ...__privateGet(this, _state).formTouched, [key]: true };
|
|
429
|
+
let formErrors = { ...__privateGet(this, _state).formErrors };
|
|
430
|
+
if (__privateGet(this, _formSchema) && __privateGet(this, _state).formValidateOnChange) {
|
|
431
|
+
formErrors = __privateMethod(this, _DialogController_instances, validateFormField_fn).call(this, key, formValues, formErrors);
|
|
432
|
+
}
|
|
433
|
+
__privateMethod(this, _DialogController_instances, update_fn).call(this, { formValues, formTouched, formErrors });
|
|
434
|
+
}
|
|
435
|
+
touchFormField(key) {
|
|
436
|
+
const formTouched = { ...__privateGet(this, _state).formTouched, [key]: true };
|
|
437
|
+
let formErrors = { ...__privateGet(this, _state).formErrors };
|
|
438
|
+
if (__privateGet(this, _formSchema) && __privateGet(this, _state).formValidateOnBlur) {
|
|
439
|
+
formErrors = __privateMethod(this, _DialogController_instances, validateFormField_fn).call(this, key, __privateGet(this, _state).formValues, formErrors);
|
|
440
|
+
}
|
|
441
|
+
__privateMethod(this, _DialogController_instances, update_fn).call(this, { formTouched, formErrors });
|
|
442
|
+
}
|
|
443
|
+
// ─── Step Form ───────────────────────────────────────────
|
|
444
|
+
showStepForm(steps, options) {
|
|
445
|
+
__privateMethod(this, _DialogController_instances, clearTimer_fn).call(this);
|
|
446
|
+
__privateSet(this, _stepFormSchemas, steps.map((s) => s.schema ?? null));
|
|
447
|
+
__privateSet(this, _stepFormResults, {});
|
|
448
|
+
const stepFormSteps = steps.map((s) => {
|
|
449
|
+
const fields = s.schema ? extractFormFields(s.schema) : [];
|
|
450
|
+
const values = {};
|
|
451
|
+
for (const f of fields) {
|
|
452
|
+
if (f.defaultValue !== void 0) values[f.key] = f.defaultValue;
|
|
453
|
+
}
|
|
454
|
+
if (s.defaultValues) Object.assign(values, s.defaultValues);
|
|
455
|
+
return {
|
|
456
|
+
key: s.key,
|
|
457
|
+
label: s.label,
|
|
458
|
+
description: s.description ?? "",
|
|
459
|
+
fields,
|
|
460
|
+
values,
|
|
461
|
+
errors: {},
|
|
462
|
+
touched: {},
|
|
463
|
+
layout: s.layout ?? {}
|
|
464
|
+
};
|
|
465
|
+
});
|
|
466
|
+
__privateMethod(this, _DialogController_instances, update_fn).call(this, {
|
|
467
|
+
open: true,
|
|
468
|
+
dialogType: "step-form",
|
|
469
|
+
title: options?.title ?? "",
|
|
470
|
+
label: "",
|
|
471
|
+
description: "",
|
|
472
|
+
icon: null,
|
|
473
|
+
showConfirmButton: false,
|
|
474
|
+
showCancelButton: false,
|
|
475
|
+
allowOutsideClick: options?.allowOutsideClick ?? false,
|
|
476
|
+
allowEscapeKey: options?.allowEscapeKey ?? true,
|
|
477
|
+
progress: null,
|
|
478
|
+
timer: null,
|
|
479
|
+
stepFormSteps,
|
|
480
|
+
stepFormCurrentIndex: 0,
|
|
481
|
+
stepFormNextText: options?.nextButtonText ?? "\u6B21\u3078",
|
|
482
|
+
stepFormPrevText: options?.prevButtonText ?? "\u623B\u308B",
|
|
483
|
+
stepFormSubmitText: options?.submitButtonText ?? "OK",
|
|
484
|
+
cancelButtonText: options?.cancelButtonText ?? "\u30AD\u30E3\u30F3\u30BB\u30EB"
|
|
485
|
+
});
|
|
486
|
+
return __privateMethod(this, _DialogController_instances, createPromise_fn).call(this, null).then((r) => {
|
|
487
|
+
const data = __privateGet(this, _stepFormResults);
|
|
488
|
+
__privateSet(this, _stepFormSchemas, []);
|
|
489
|
+
__privateSet(this, _stepFormResults, {});
|
|
490
|
+
return r.isConfirmed ? data : null;
|
|
491
|
+
});
|
|
492
|
+
}
|
|
493
|
+
onStepNext() {
|
|
494
|
+
const s = __privateGet(this, _state);
|
|
495
|
+
const idx = s.stepFormCurrentIndex;
|
|
496
|
+
const step = s.stepFormSteps[idx];
|
|
497
|
+
if (!step) return;
|
|
498
|
+
const schema = __privateGet(this, _stepFormSchemas)[idx];
|
|
499
|
+
if (schema) {
|
|
500
|
+
const result = schema.safeParse(step.values);
|
|
501
|
+
if (!result.success) {
|
|
502
|
+
const errors = {};
|
|
503
|
+
for (const issue of result.error.issues) {
|
|
504
|
+
const key = issue.path[0]?.toString();
|
|
505
|
+
if (key && !errors[key]) errors[key] = issue.message;
|
|
506
|
+
}
|
|
507
|
+
const touched = {};
|
|
508
|
+
for (const f of step.fields) touched[f.key] = true;
|
|
509
|
+
__privateMethod(this, _DialogController_instances, updateCurrentStep_fn).call(this, { errors, touched });
|
|
510
|
+
return;
|
|
511
|
+
}
|
|
512
|
+
__privateGet(this, _stepFormResults)[step.key] = result.data;
|
|
513
|
+
}
|
|
514
|
+
const isLast = idx === s.stepFormSteps.length - 1;
|
|
515
|
+
if (isLast) {
|
|
516
|
+
const r = { isConfirmed: true, isCanceled: false, isDismissed: false };
|
|
517
|
+
__privateMethod(this, _DialogController_instances, update_fn).call(this, { ...createInitialState(), open: false });
|
|
518
|
+
__privateMethod(this, _DialogController_instances, resolve_fn).call(this, r);
|
|
519
|
+
return;
|
|
520
|
+
}
|
|
521
|
+
__privateMethod(this, _DialogController_instances, update_fn).call(this, { stepFormCurrentIndex: idx + 1 });
|
|
522
|
+
}
|
|
523
|
+
onStepPrev() {
|
|
524
|
+
const idx = __privateGet(this, _state).stepFormCurrentIndex;
|
|
525
|
+
if (idx <= 0) return;
|
|
526
|
+
__privateMethod(this, _DialogController_instances, update_fn).call(this, { stepFormCurrentIndex: idx - 1 });
|
|
527
|
+
}
|
|
528
|
+
updateStepFormField(fieldKey, value) {
|
|
529
|
+
const s = __privateGet(this, _state);
|
|
530
|
+
const idx = s.stepFormCurrentIndex;
|
|
531
|
+
const step = s.stepFormSteps[idx];
|
|
532
|
+
if (!step) return;
|
|
533
|
+
const values = { ...step.values, [fieldKey]: value };
|
|
534
|
+
const touched = { ...step.touched, [fieldKey]: true };
|
|
535
|
+
let errors = { ...step.errors };
|
|
536
|
+
const schema = __privateGet(this, _stepFormSchemas)[idx];
|
|
537
|
+
if (schema && s.formValidateOnChange) {
|
|
538
|
+
errors = __privateMethod(this, _DialogController_instances, validateStepField_fn).call(this, schema, fieldKey, values, errors);
|
|
539
|
+
}
|
|
540
|
+
__privateMethod(this, _DialogController_instances, updateCurrentStep_fn).call(this, { values, touched, errors });
|
|
541
|
+
}
|
|
542
|
+
touchStepFormField(fieldKey) {
|
|
543
|
+
const s = __privateGet(this, _state);
|
|
544
|
+
const idx = s.stepFormCurrentIndex;
|
|
545
|
+
const step = s.stepFormSteps[idx];
|
|
546
|
+
if (!step) return;
|
|
547
|
+
const touched = { ...step.touched, [fieldKey]: true };
|
|
548
|
+
let errors = { ...step.errors };
|
|
549
|
+
const schema = __privateGet(this, _stepFormSchemas)[idx];
|
|
550
|
+
if (schema && s.formValidateOnBlur) {
|
|
551
|
+
errors = __privateMethod(this, _DialogController_instances, validateStepField_fn).call(this, schema, fieldKey, step.values, errors);
|
|
552
|
+
}
|
|
553
|
+
__privateMethod(this, _DialogController_instances, updateCurrentStep_fn).call(this, { touched, errors });
|
|
554
|
+
}
|
|
223
555
|
// ─── Button actions (called from the component) ──────────
|
|
224
556
|
onConfirm() {
|
|
225
557
|
__privateMethod(this, _DialogController_instances, clearTimer_fn).call(this);
|
|
558
|
+
if (__privateGet(this, _state).dialogType === "form" && __privateGet(this, _formSchema)) {
|
|
559
|
+
const result = __privateGet(this, _formSchema).safeParse(__privateGet(this, _state).formValues);
|
|
560
|
+
if (!result.success) {
|
|
561
|
+
const formErrors = {};
|
|
562
|
+
for (const issue of result.error.issues) {
|
|
563
|
+
const key = issue.path[0]?.toString();
|
|
564
|
+
if (key && !formErrors[key]) {
|
|
565
|
+
formErrors[key] = issue.message;
|
|
566
|
+
}
|
|
567
|
+
}
|
|
568
|
+
const formTouched = {};
|
|
569
|
+
for (const field of __privateGet(this, _state).formFields) {
|
|
570
|
+
formTouched[field.key] = true;
|
|
571
|
+
}
|
|
572
|
+
__privateMethod(this, _DialogController_instances, update_fn).call(this, { formErrors, formTouched });
|
|
573
|
+
return;
|
|
574
|
+
}
|
|
575
|
+
__privateSet(this, _formResult, result.data);
|
|
576
|
+
}
|
|
226
577
|
const r = { isConfirmed: true, isCanceled: false, isDismissed: false };
|
|
227
578
|
__privateMethod(this, _DialogController_instances, update_fn).call(this, { ...createInitialState(), open: false });
|
|
228
579
|
__privateMethod(this, _DialogController_instances, resolve_fn).call(this, r);
|
|
@@ -246,6 +597,10 @@ _state = new WeakMap();
|
|
|
246
597
|
_listeners = new WeakMap();
|
|
247
598
|
_resolver = new WeakMap();
|
|
248
599
|
_timerId = new WeakMap();
|
|
600
|
+
_formSchema = new WeakMap();
|
|
601
|
+
_formResult = new WeakMap();
|
|
602
|
+
_stepFormSchemas = new WeakMap();
|
|
603
|
+
_stepFormResults = new WeakMap();
|
|
249
604
|
_DialogController_instances = new WeakSet();
|
|
250
605
|
emit_fn = function() {
|
|
251
606
|
const snapshot = { ...__privateGet(this, _state) };
|
|
@@ -255,6 +610,47 @@ update_fn = function(patch) {
|
|
|
255
610
|
Object.assign(__privateGet(this, _state), patch);
|
|
256
611
|
__privateMethod(this, _DialogController_instances, emit_fn).call(this);
|
|
257
612
|
};
|
|
613
|
+
validateFormField_fn = function(key, values, errors) {
|
|
614
|
+
const result = __privateGet(this, _formSchema).safeParse(values);
|
|
615
|
+
const updated = { ...errors };
|
|
616
|
+
if (result.success) {
|
|
617
|
+
delete updated[key];
|
|
618
|
+
} else {
|
|
619
|
+
const fieldIssue = result.error.issues.find(
|
|
620
|
+
(issue) => issue.path[0]?.toString() === key
|
|
621
|
+
);
|
|
622
|
+
if (fieldIssue) {
|
|
623
|
+
updated[key] = fieldIssue.message;
|
|
624
|
+
} else {
|
|
625
|
+
delete updated[key];
|
|
626
|
+
}
|
|
627
|
+
}
|
|
628
|
+
return updated;
|
|
629
|
+
};
|
|
630
|
+
updateCurrentStep_fn = function(patch) {
|
|
631
|
+
const idx = __privateGet(this, _state).stepFormCurrentIndex;
|
|
632
|
+
const stepFormSteps = __privateGet(this, _state).stepFormSteps.map(
|
|
633
|
+
(st, i) => i === idx ? { ...st, ...patch } : st
|
|
634
|
+
);
|
|
635
|
+
__privateMethod(this, _DialogController_instances, update_fn).call(this, { stepFormSteps });
|
|
636
|
+
};
|
|
637
|
+
validateStepField_fn = function(schema, fieldKey, values, errors) {
|
|
638
|
+
const result = schema.safeParse(values);
|
|
639
|
+
const updated = { ...errors };
|
|
640
|
+
if (result.success) {
|
|
641
|
+
delete updated[fieldKey];
|
|
642
|
+
} else {
|
|
643
|
+
const issue = result.error.issues.find(
|
|
644
|
+
(iss) => iss.path[0]?.toString() === fieldKey
|
|
645
|
+
);
|
|
646
|
+
if (issue) {
|
|
647
|
+
updated[fieldKey] = issue.message;
|
|
648
|
+
} else {
|
|
649
|
+
delete updated[fieldKey];
|
|
650
|
+
}
|
|
651
|
+
}
|
|
652
|
+
return updated;
|
|
653
|
+
};
|
|
258
654
|
// ─── Internal ────────────────────────────────────────────
|
|
259
655
|
createPromise_fn = function(timer) {
|
|
260
656
|
return new Promise((resolve) => {
|
|
@@ -343,6 +739,24 @@ var overlayStyles = import_lit.css`
|
|
|
343
739
|
--dialog-spinner-track: rgb(59 130 246 / 0.2);
|
|
344
740
|
--dialog-spinner-arc: var(--dialog-primary);
|
|
345
741
|
|
|
742
|
+
/* Form */
|
|
743
|
+
--dialog-form-width: 500px;
|
|
744
|
+
--dialog-form-max-height: 60vh;
|
|
745
|
+
--dialog-form-gap: 16px;
|
|
746
|
+
--dialog-form-columns: 1;
|
|
747
|
+
--dialog-form-label-color: #374151;
|
|
748
|
+
--dialog-form-label-size: 13px;
|
|
749
|
+
--dialog-form-label-weight: 500;
|
|
750
|
+
--dialog-form-input-bg: #fff;
|
|
751
|
+
--dialog-form-input-border: #d1d5db;
|
|
752
|
+
--dialog-form-input-border-focus: var(--dialog-primary);
|
|
753
|
+
--dialog-form-input-radius: 6px;
|
|
754
|
+
--dialog-form-input-padding: 8px 12px;
|
|
755
|
+
--dialog-form-input-font-size: 14px;
|
|
756
|
+
--dialog-form-error-color: var(--dialog-error);
|
|
757
|
+
--dialog-form-hint-color: #9ca3af;
|
|
758
|
+
--dialog-form-required-color: var(--dialog-error);
|
|
759
|
+
|
|
346
760
|
display: contents;
|
|
347
761
|
font-family: var(--dialog-font-family);
|
|
348
762
|
color: var(--dialog-text-color);
|
|
@@ -494,8 +908,6 @@ var overlayStyles = import_lit.css`
|
|
|
494
908
|
}
|
|
495
909
|
}
|
|
496
910
|
|
|
497
|
-
/* spin と spinner-enter は同じ transform を書き換えるため衝突する。
|
|
498
|
-
ラッパーでスケール/フェードを担い、.spinner は回転専用にする。 */
|
|
499
911
|
.spinner-wrap {
|
|
500
912
|
font-size: var(--dialog-spinner-size);
|
|
501
913
|
width: 1em;
|
|
@@ -978,6 +1390,204 @@ var overlayStyles = import_lit.css`
|
|
|
978
1390
|
background-color: #e5e7eb;
|
|
979
1391
|
transition: background-color 400ms ease;
|
|
980
1392
|
}
|
|
1393
|
+
|
|
1394
|
+
/* ─── Form ─── */
|
|
1395
|
+
|
|
1396
|
+
@media (min-width: 640px) {
|
|
1397
|
+
.card[data-type='form'] {
|
|
1398
|
+
width: var(--dialog-form-width);
|
|
1399
|
+
}
|
|
1400
|
+
}
|
|
1401
|
+
|
|
1402
|
+
.form-scroll-container {
|
|
1403
|
+
max-height: var(--dialog-form-max-height);
|
|
1404
|
+
overflow-y: auto;
|
|
1405
|
+
width: 100%;
|
|
1406
|
+
padding: 4px 0;
|
|
1407
|
+
}
|
|
1408
|
+
|
|
1409
|
+
.form-grid {
|
|
1410
|
+
display: grid;
|
|
1411
|
+
grid-template-columns: repeat(var(--dialog-form-columns, 1), 1fr);
|
|
1412
|
+
gap: var(--dialog-form-gap);
|
|
1413
|
+
width: 100%;
|
|
1414
|
+
}
|
|
1415
|
+
|
|
1416
|
+
@media (max-width: 639px) {
|
|
1417
|
+
.form-grid {
|
|
1418
|
+
grid-template-columns: 1fr !important;
|
|
1419
|
+
}
|
|
1420
|
+
}
|
|
1421
|
+
|
|
1422
|
+
.form-field {
|
|
1423
|
+
display: flex;
|
|
1424
|
+
flex-direction: column;
|
|
1425
|
+
gap: 4px;
|
|
1426
|
+
text-align: left;
|
|
1427
|
+
}
|
|
1428
|
+
|
|
1429
|
+
.form-field[data-type='checkbox'] {
|
|
1430
|
+
grid-column: 1 / -1;
|
|
1431
|
+
}
|
|
1432
|
+
|
|
1433
|
+
.form-label {
|
|
1434
|
+
font-size: var(--dialog-form-label-size);
|
|
1435
|
+
font-weight: var(--dialog-form-label-weight);
|
|
1436
|
+
color: var(--dialog-form-label-color);
|
|
1437
|
+
}
|
|
1438
|
+
|
|
1439
|
+
.form-required {
|
|
1440
|
+
color: var(--dialog-form-required-color);
|
|
1441
|
+
margin-left: 2px;
|
|
1442
|
+
}
|
|
1443
|
+
|
|
1444
|
+
.form-input,
|
|
1445
|
+
.form-select {
|
|
1446
|
+
padding: var(--dialog-form-input-padding);
|
|
1447
|
+
font-size: var(--dialog-form-input-font-size);
|
|
1448
|
+
font-family: inherit;
|
|
1449
|
+
background: var(--dialog-form-input-bg);
|
|
1450
|
+
border: 1px solid var(--dialog-form-input-border);
|
|
1451
|
+
border-radius: var(--dialog-form-input-radius);
|
|
1452
|
+
color: var(--dialog-text-color);
|
|
1453
|
+
outline: none;
|
|
1454
|
+
transition:
|
|
1455
|
+
border-color 150ms ease,
|
|
1456
|
+
box-shadow 150ms ease;
|
|
1457
|
+
width: 100%;
|
|
1458
|
+
box-sizing: border-box;
|
|
1459
|
+
}
|
|
1460
|
+
|
|
1461
|
+
.form-input:focus,
|
|
1462
|
+
.form-select:focus {
|
|
1463
|
+
border-color: var(--dialog-form-input-border-focus);
|
|
1464
|
+
box-shadow: 0 0 0 3px rgb(59 130 246 / 0.1);
|
|
1465
|
+
}
|
|
1466
|
+
|
|
1467
|
+
.form-field[data-error] .form-input,
|
|
1468
|
+
.form-field[data-error] .form-select {
|
|
1469
|
+
border-color: var(--dialog-form-error-color);
|
|
1470
|
+
}
|
|
1471
|
+
|
|
1472
|
+
.form-field[data-error] .form-input:focus,
|
|
1473
|
+
.form-field[data-error] .form-select:focus {
|
|
1474
|
+
box-shadow: 0 0 0 3px rgb(239 68 68 / 0.1);
|
|
1475
|
+
}
|
|
1476
|
+
|
|
1477
|
+
.form-error {
|
|
1478
|
+
font-size: 12px;
|
|
1479
|
+
color: var(--dialog-form-error-color);
|
|
1480
|
+
min-height: 1em;
|
|
1481
|
+
}
|
|
1482
|
+
|
|
1483
|
+
.form-hint {
|
|
1484
|
+
font-size: 12px;
|
|
1485
|
+
color: var(--dialog-form-hint-color);
|
|
1486
|
+
}
|
|
1487
|
+
|
|
1488
|
+
.form-checkbox {
|
|
1489
|
+
width: 18px;
|
|
1490
|
+
height: 18px;
|
|
1491
|
+
accent-color: var(--dialog-primary);
|
|
1492
|
+
cursor: pointer;
|
|
1493
|
+
flex-shrink: 0;
|
|
1494
|
+
}
|
|
1495
|
+
|
|
1496
|
+
.form-checkbox-label {
|
|
1497
|
+
display: flex;
|
|
1498
|
+
align-items: center;
|
|
1499
|
+
gap: 8px;
|
|
1500
|
+
cursor: pointer;
|
|
1501
|
+
font-size: var(--dialog-form-input-font-size);
|
|
1502
|
+
color: var(--dialog-form-label-color);
|
|
1503
|
+
}
|
|
1504
|
+
|
|
1505
|
+
.form-checkbox-text {
|
|
1506
|
+
font-size: var(--dialog-form-label-size);
|
|
1507
|
+
font-weight: var(--dialog-form-label-weight);
|
|
1508
|
+
color: var(--dialog-form-label-color);
|
|
1509
|
+
}
|
|
1510
|
+
|
|
1511
|
+
.form-group {
|
|
1512
|
+
border: 1px solid var(--dialog-card-border);
|
|
1513
|
+
border-radius: var(--dialog-form-input-radius);
|
|
1514
|
+
padding: 16px;
|
|
1515
|
+
margin: 0 0 8px;
|
|
1516
|
+
width: 100%;
|
|
1517
|
+
box-sizing: border-box;
|
|
1518
|
+
}
|
|
1519
|
+
|
|
1520
|
+
.form-group-label {
|
|
1521
|
+
font-size: var(--dialog-form-label-size);
|
|
1522
|
+
font-weight: 600;
|
|
1523
|
+
color: var(--dialog-form-label-color);
|
|
1524
|
+
padding: 0 4px;
|
|
1525
|
+
}
|
|
1526
|
+
|
|
1527
|
+
/* ─── Step Form ─── */
|
|
1528
|
+
|
|
1529
|
+
@media (min-width: 640px) {
|
|
1530
|
+
.card[data-type='step-form'] {
|
|
1531
|
+
width: var(--dialog-form-width);
|
|
1532
|
+
}
|
|
1533
|
+
}
|
|
1534
|
+
|
|
1535
|
+
.step-form-counter {
|
|
1536
|
+
font-size: 12px;
|
|
1537
|
+
color: var(--dialog-form-hint-color);
|
|
1538
|
+
text-align: center;
|
|
1539
|
+
margin: 0 0 4px;
|
|
1540
|
+
}
|
|
1541
|
+
|
|
1542
|
+
.actions-step-form {
|
|
1543
|
+
display: flex;
|
|
1544
|
+
flex-direction: row;
|
|
1545
|
+
justify-content: space-between;
|
|
1546
|
+
align-items: center;
|
|
1547
|
+
gap: 8px;
|
|
1548
|
+
margin-top: 20px;
|
|
1549
|
+
width: 100%;
|
|
1550
|
+
}
|
|
1551
|
+
|
|
1552
|
+
.step-form-nav {
|
|
1553
|
+
display: flex;
|
|
1554
|
+
flex-direction: row;
|
|
1555
|
+
gap: 8px;
|
|
1556
|
+
align-items: center;
|
|
1557
|
+
}
|
|
1558
|
+
|
|
1559
|
+
.btn-prev {
|
|
1560
|
+
padding: var(--dialog-btn-padding);
|
|
1561
|
+
font-size: var(--dialog-btn-font-size);
|
|
1562
|
+
font-family: inherit;
|
|
1563
|
+
font-weight: 500;
|
|
1564
|
+
border-radius: var(--dialog-btn-radius);
|
|
1565
|
+
cursor: pointer;
|
|
1566
|
+
border: 1px solid var(--dialog-form-input-border);
|
|
1567
|
+
background: transparent;
|
|
1568
|
+
color: var(--dialog-text-color);
|
|
1569
|
+
transition: background-color 120ms ease, border-color 120ms ease;
|
|
1570
|
+
}
|
|
1571
|
+
|
|
1572
|
+
.btn-prev:hover {
|
|
1573
|
+
background: #f9fafb;
|
|
1574
|
+
border-color: #9ca3af;
|
|
1575
|
+
}
|
|
1576
|
+
|
|
1577
|
+
.btn-prev:active {
|
|
1578
|
+
transform: scale(0.98);
|
|
1579
|
+
}
|
|
1580
|
+
|
|
1581
|
+
@media (max-width: 639px) {
|
|
1582
|
+
.actions-step-form {
|
|
1583
|
+
flex-direction: column-reverse;
|
|
1584
|
+
}
|
|
1585
|
+
|
|
1586
|
+
.step-form-nav {
|
|
1587
|
+
width: 100%;
|
|
1588
|
+
justify-content: flex-end;
|
|
1589
|
+
}
|
|
1590
|
+
}
|
|
981
1591
|
`;
|
|
982
1592
|
|
|
983
1593
|
// src/overlay-dialog.ts
|
|
@@ -1001,6 +1611,7 @@ var OverlayDialog = class extends import_lit2.LitElement {
|
|
|
1001
1611
|
this._unsubscribe = this.controller.subscribe((s) => {
|
|
1002
1612
|
const wasOpen = this._state.open;
|
|
1003
1613
|
const prevDialogType = this._state.dialogType;
|
|
1614
|
+
const prevStepIndex = this._state.stepFormCurrentIndex;
|
|
1004
1615
|
if (s.open && !wasOpen) {
|
|
1005
1616
|
this._isClosing = false;
|
|
1006
1617
|
clearTimeout(this._closeTimer);
|
|
@@ -1015,6 +1626,8 @@ var OverlayDialog = class extends import_lit2.LitElement {
|
|
|
1015
1626
|
}
|
|
1016
1627
|
if (s.open && s.dialogType !== prevDialogType) {
|
|
1017
1628
|
this._bodyKey++;
|
|
1629
|
+
} else if (s.open && s.dialogType === "step-form" && s.stepFormCurrentIndex !== prevStepIndex) {
|
|
1630
|
+
this._bodyKey++;
|
|
1018
1631
|
}
|
|
1019
1632
|
this._state = s;
|
|
1020
1633
|
this._syncBodyScroll(s.open);
|
|
@@ -1244,6 +1857,187 @@ var OverlayDialog = class extends import_lit2.LitElement {
|
|
|
1244
1857
|
</ul>
|
|
1245
1858
|
`;
|
|
1246
1859
|
}
|
|
1860
|
+
// ─── Form Helpers ────────────────────────────────────────
|
|
1861
|
+
_createFormContext() {
|
|
1862
|
+
const s = this._state;
|
|
1863
|
+
return {
|
|
1864
|
+
getValue: (k) => s.formValues[k],
|
|
1865
|
+
getError: (k) => s.formErrors[k] ?? "",
|
|
1866
|
+
getTouched: (k) => !!s.formTouched[k],
|
|
1867
|
+
onUpdate: (k, v) => this.controller.updateFormField(k, v),
|
|
1868
|
+
onBlur: (k) => this.controller.touchFormField(k)
|
|
1869
|
+
};
|
|
1870
|
+
}
|
|
1871
|
+
_createStepFormContext() {
|
|
1872
|
+
const s = this._state;
|
|
1873
|
+
const step = s.stepFormSteps[s.stepFormCurrentIndex];
|
|
1874
|
+
return {
|
|
1875
|
+
getValue: (k) => step?.values[k],
|
|
1876
|
+
getError: (k) => step?.errors[k] ?? "",
|
|
1877
|
+
getTouched: (k) => !!step?.touched[k],
|
|
1878
|
+
onUpdate: (k, v) => this.controller.updateStepFormField(k, v),
|
|
1879
|
+
onBlur: (k) => this.controller.touchStepFormField(k)
|
|
1880
|
+
};
|
|
1881
|
+
}
|
|
1882
|
+
_getOrderedFields(fields, layout) {
|
|
1883
|
+
const order = layout.fieldOrder;
|
|
1884
|
+
if (!order?.length) return fields;
|
|
1885
|
+
const fieldMap = new Map(fields.map((f) => [f.key, f]));
|
|
1886
|
+
const ordered = [];
|
|
1887
|
+
for (const key of order) {
|
|
1888
|
+
const f = fieldMap.get(key);
|
|
1889
|
+
if (f) {
|
|
1890
|
+
ordered.push(f);
|
|
1891
|
+
fieldMap.delete(key);
|
|
1892
|
+
}
|
|
1893
|
+
}
|
|
1894
|
+
for (const f of fieldMap.values()) {
|
|
1895
|
+
ordered.push(f);
|
|
1896
|
+
}
|
|
1897
|
+
return ordered;
|
|
1898
|
+
}
|
|
1899
|
+
_renderFormGrid(fields, columns, gap, ctx) {
|
|
1900
|
+
return import_lit2.html`
|
|
1901
|
+
<div class="form-grid" style="--dialog-form-columns:${columns}; gap:${gap}">
|
|
1902
|
+
${fields.map((f) => this._renderFormField(f, ctx))}
|
|
1903
|
+
</div>
|
|
1904
|
+
`;
|
|
1905
|
+
}
|
|
1906
|
+
_renderGroupedForm(allFields, groups, layout, ctx) {
|
|
1907
|
+
const fieldMap = new Map(allFields.map((f) => [f.key, f]));
|
|
1908
|
+
const usedKeys = /* @__PURE__ */ new Set();
|
|
1909
|
+
const gap = layout.gap ?? "16px";
|
|
1910
|
+
const groupFragments = groups.map((group) => {
|
|
1911
|
+
const groupFields = [];
|
|
1912
|
+
for (const key of group.fields) {
|
|
1913
|
+
const f = fieldMap.get(key);
|
|
1914
|
+
if (f) {
|
|
1915
|
+
groupFields.push(f);
|
|
1916
|
+
usedKeys.add(key);
|
|
1917
|
+
}
|
|
1918
|
+
}
|
|
1919
|
+
if (!groupFields.length) return import_lit2.nothing;
|
|
1920
|
+
const cols = group.columns ?? layout.columns ?? 1;
|
|
1921
|
+
return import_lit2.html`
|
|
1922
|
+
<fieldset class="form-group">
|
|
1923
|
+
${group.label ? import_lit2.html`<legend class="form-group-label">${group.label}</legend>` : import_lit2.nothing}
|
|
1924
|
+
${this._renderFormGrid(groupFields, cols, gap, ctx)}
|
|
1925
|
+
</fieldset>
|
|
1926
|
+
`;
|
|
1927
|
+
});
|
|
1928
|
+
const remaining = allFields.filter((f) => !usedKeys.has(f.key));
|
|
1929
|
+
return import_lit2.html`
|
|
1930
|
+
${groupFragments}
|
|
1931
|
+
${remaining.length ? this._renderFormGrid(remaining, layout.columns ?? 1, gap, ctx) : import_lit2.nothing}
|
|
1932
|
+
`;
|
|
1933
|
+
}
|
|
1934
|
+
_renderForm(fields, layout, ctx) {
|
|
1935
|
+
const ordered = this._getOrderedFields(fields, layout);
|
|
1936
|
+
const gap = layout.gap ?? "16px";
|
|
1937
|
+
if (layout.groups?.length) {
|
|
1938
|
+
return this._renderGroupedForm(ordered, layout.groups, layout, ctx);
|
|
1939
|
+
}
|
|
1940
|
+
return this._renderFormGrid(ordered, layout.columns ?? 1, gap, ctx);
|
|
1941
|
+
}
|
|
1942
|
+
_renderFormField(field, ctx) {
|
|
1943
|
+
const value = ctx.getValue(field.key);
|
|
1944
|
+
const error = ctx.getError(field.key);
|
|
1945
|
+
const touched = ctx.getTouched(field.key);
|
|
1946
|
+
const showError = touched && !!error;
|
|
1947
|
+
if (field.inputType === "checkbox") {
|
|
1948
|
+
return import_lit2.html`
|
|
1949
|
+
<div class="form-field" data-type="checkbox" ?data-error=${showError}>
|
|
1950
|
+
<label class="form-checkbox-label">
|
|
1951
|
+
<input
|
|
1952
|
+
type="checkbox"
|
|
1953
|
+
class="form-checkbox"
|
|
1954
|
+
.checked=${!!value}
|
|
1955
|
+
@change=${(e) => ctx.onUpdate(field.key, e.target.checked)}
|
|
1956
|
+
@blur=${() => ctx.onBlur(field.key)}
|
|
1957
|
+
/>
|
|
1958
|
+
<span class="form-checkbox-text">
|
|
1959
|
+
${field.label}
|
|
1960
|
+
${field.required ? import_lit2.html`<span class="form-required">*</span>` : import_lit2.nothing}
|
|
1961
|
+
</span>
|
|
1962
|
+
</label>
|
|
1963
|
+
${showError ? import_lit2.html`<span class="form-error">${error}</span>` : import_lit2.nothing}
|
|
1964
|
+
</div>
|
|
1965
|
+
`;
|
|
1966
|
+
}
|
|
1967
|
+
return import_lit2.html`
|
|
1968
|
+
<div class="form-field" data-type=${field.inputType} ?data-error=${showError}>
|
|
1969
|
+
<label class="form-label" for="form-${field.key}">
|
|
1970
|
+
${field.label} ${field.required ? import_lit2.html`<span class="form-required">*</span>` : import_lit2.nothing}
|
|
1971
|
+
</label>
|
|
1972
|
+
${field.description ? import_lit2.html`<span class="form-hint">${field.description}</span>` : import_lit2.nothing}
|
|
1973
|
+
${this._renderFormInput(field, value, ctx)}
|
|
1974
|
+
${showError ? import_lit2.html`<span class="form-error">${error}</span>` : import_lit2.nothing}
|
|
1975
|
+
</div>
|
|
1976
|
+
`;
|
|
1977
|
+
}
|
|
1978
|
+
_renderFormInput(field, value, ctx) {
|
|
1979
|
+
switch (field.inputType) {
|
|
1980
|
+
case "select":
|
|
1981
|
+
return import_lit2.html`
|
|
1982
|
+
<select
|
|
1983
|
+
class="form-select"
|
|
1984
|
+
id="form-${field.key}"
|
|
1985
|
+
@change=${(e) => ctx.onUpdate(field.key, e.target.value)}
|
|
1986
|
+
@blur=${() => ctx.onBlur(field.key)}
|
|
1987
|
+
>
|
|
1988
|
+
<option value="" ?selected=${!value}>選択してください</option>
|
|
1989
|
+
${field.options.map(
|
|
1990
|
+
(opt) => import_lit2.html`<option value=${opt} ?selected=${value === opt}>${opt}</option>`
|
|
1991
|
+
)}
|
|
1992
|
+
</select>
|
|
1993
|
+
`;
|
|
1994
|
+
case "number":
|
|
1995
|
+
return import_lit2.html`
|
|
1996
|
+
<input
|
|
1997
|
+
type="number"
|
|
1998
|
+
class="form-input"
|
|
1999
|
+
id="form-${field.key}"
|
|
2000
|
+
.value=${value != null ? String(value) : ""}
|
|
2001
|
+
min=${field.min ?? import_lit2.nothing}
|
|
2002
|
+
max=${field.max ?? import_lit2.nothing}
|
|
2003
|
+
placeholder=${field.placeholder || import_lit2.nothing}
|
|
2004
|
+
@input=${(e) => {
|
|
2005
|
+
const v = e.target.valueAsNumber;
|
|
2006
|
+
ctx.onUpdate(field.key, Number.isNaN(v) ? void 0 : v);
|
|
2007
|
+
}}
|
|
2008
|
+
@blur=${() => ctx.onBlur(field.key)}
|
|
2009
|
+
/>
|
|
2010
|
+
`;
|
|
2011
|
+
case "date":
|
|
2012
|
+
return import_lit2.html`
|
|
2013
|
+
<input
|
|
2014
|
+
type="date"
|
|
2015
|
+
class="form-input"
|
|
2016
|
+
id="form-${field.key}"
|
|
2017
|
+
.value=${value != null ? String(value) : ""}
|
|
2018
|
+
@input=${(e) => {
|
|
2019
|
+
const str = e.target.value;
|
|
2020
|
+
ctx.onUpdate(field.key, str || void 0);
|
|
2021
|
+
}}
|
|
2022
|
+
@blur=${() => ctx.onBlur(field.key)}
|
|
2023
|
+
/>
|
|
2024
|
+
`;
|
|
2025
|
+
default:
|
|
2026
|
+
return import_lit2.html`
|
|
2027
|
+
<input
|
|
2028
|
+
type=${field.inputType}
|
|
2029
|
+
class="form-input"
|
|
2030
|
+
id="form-${field.key}"
|
|
2031
|
+
.value=${value ?? ""}
|
|
2032
|
+
minlength=${field.minLength ?? import_lit2.nothing}
|
|
2033
|
+
maxlength=${field.maxLength ?? import_lit2.nothing}
|
|
2034
|
+
placeholder=${field.placeholder || import_lit2.nothing}
|
|
2035
|
+
@input=${(e) => ctx.onUpdate(field.key, e.target.value)}
|
|
2036
|
+
@blur=${() => ctx.onBlur(field.key)}
|
|
2037
|
+
/>
|
|
2038
|
+
`;
|
|
2039
|
+
}
|
|
2040
|
+
}
|
|
1247
2041
|
_renderButtons() {
|
|
1248
2042
|
const s = this._state;
|
|
1249
2043
|
if (!s.showConfirmButton && !s.showCancelButton) return import_lit2.nothing;
|
|
@@ -1258,6 +2052,39 @@ var OverlayDialog = class extends import_lit2.LitElement {
|
|
|
1258
2052
|
</div>
|
|
1259
2053
|
`;
|
|
1260
2054
|
}
|
|
2055
|
+
// ─── Step Form Helpers ───────────────────────────────────
|
|
2056
|
+
_renderStepFormButtons() {
|
|
2057
|
+
const s = this._state;
|
|
2058
|
+
const isFirst = s.stepFormCurrentIndex === 0;
|
|
2059
|
+
const isLast = s.stepFormCurrentIndex === s.stepFormSteps.length - 1;
|
|
2060
|
+
const submitText = isLast ? s.stepFormSubmitText : s.stepFormNextText;
|
|
2061
|
+
return import_lit2.html`
|
|
2062
|
+
<div class="actions actions-step-form">
|
|
2063
|
+
<button class="btn btn-cancel" @click=${() => this.controller.onCancel()}>
|
|
2064
|
+
${s.cancelButtonText}
|
|
2065
|
+
</button>
|
|
2066
|
+
<div class="step-form-nav">
|
|
2067
|
+
${isFirst ? import_lit2.nothing : import_lit2.html`
|
|
2068
|
+
<button class="btn btn-prev" @click=${() => this.controller.onStepPrev()}>
|
|
2069
|
+
${s.stepFormPrevText}
|
|
2070
|
+
</button>
|
|
2071
|
+
`}
|
|
2072
|
+
<button class="btn btn-confirm" @click=${() => this.controller.onStepNext()}>
|
|
2073
|
+
${submitText}
|
|
2074
|
+
</button>
|
|
2075
|
+
</div>
|
|
2076
|
+
</div>
|
|
2077
|
+
`;
|
|
2078
|
+
}
|
|
2079
|
+
_deriveStepItems() {
|
|
2080
|
+
const s = this._state;
|
|
2081
|
+
return s.stepFormSteps.map((st, i) => {
|
|
2082
|
+
let status = "pending";
|
|
2083
|
+
if (i < s.stepFormCurrentIndex) status = "done";
|
|
2084
|
+
else if (i === s.stepFormCurrentIndex) status = "active";
|
|
2085
|
+
return { key: st.key, label: st.label, status };
|
|
2086
|
+
});
|
|
2087
|
+
}
|
|
1261
2088
|
_renderBody() {
|
|
1262
2089
|
const s = this._state;
|
|
1263
2090
|
switch (s.dialogType) {
|
|
@@ -1284,16 +2111,47 @@ var OverlayDialog = class extends import_lit2.LitElement {
|
|
|
1284
2111
|
${s.label ? import_lit2.html`<p class="label">${s.label}</p>` : import_lit2.nothing}
|
|
1285
2112
|
${this._renderStepsList(s.steps)}
|
|
1286
2113
|
`;
|
|
2114
|
+
case "form": {
|
|
2115
|
+
const ctx = this._createFormContext();
|
|
2116
|
+
return import_lit2.html`
|
|
2117
|
+
${s.title ? import_lit2.html`<p class="label">${s.title}</p>` : import_lit2.nothing}
|
|
2118
|
+
${s.description ? import_lit2.html`<p class="description">${s.description}</p>` : import_lit2.nothing}
|
|
2119
|
+
<div class="form-scroll-container">
|
|
2120
|
+
${this._renderForm(s.formFields, s.formLayout, ctx)}
|
|
2121
|
+
</div>
|
|
2122
|
+
${this._renderButtons()}
|
|
2123
|
+
`;
|
|
2124
|
+
}
|
|
2125
|
+
case "step-form": {
|
|
2126
|
+
const stepItems = this._deriveStepItems();
|
|
2127
|
+
const currentStep = s.stepFormSteps[s.stepFormCurrentIndex];
|
|
2128
|
+
if (!currentStep) return import_lit2.html`${import_lit2.nothing}`;
|
|
2129
|
+
const ctx = this._createStepFormContext();
|
|
2130
|
+
const stepCount = s.stepFormSteps.length;
|
|
2131
|
+
const counterText = `${s.stepFormCurrentIndex + 1} / ${stepCount}`;
|
|
2132
|
+
return import_lit2.html`
|
|
2133
|
+
${this._renderStepsHeader(stepItems)}
|
|
2134
|
+
<p class="step-form-counter">${counterText}</p>
|
|
2135
|
+
<p class="label">${currentStep.label}</p>
|
|
2136
|
+
${currentStep.description ? import_lit2.html`<p class="description">${currentStep.description}</p>` : import_lit2.nothing}
|
|
2137
|
+
${currentStep.fields.length ? import_lit2.html`
|
|
2138
|
+
<div class="form-scroll-container">
|
|
2139
|
+
${this._renderForm(currentStep.fields, currentStep.layout, ctx)}
|
|
2140
|
+
</div>
|
|
2141
|
+
` : import_lit2.nothing}
|
|
2142
|
+
${this._renderStepFormButtons()}
|
|
2143
|
+
`;
|
|
2144
|
+
}
|
|
1287
2145
|
default:
|
|
1288
2146
|
return import_lit2.html`${import_lit2.nothing}`;
|
|
1289
2147
|
}
|
|
1290
2148
|
}
|
|
1291
2149
|
render() {
|
|
1292
2150
|
const s = this._state;
|
|
1293
|
-
const showHeaderTitle = s.title && s.dialogType !== "alert" && s.dialogType !== "confirm";
|
|
2151
|
+
const showHeaderTitle = s.title && s.dialogType !== "alert" && s.dialogType !== "confirm" && s.dialogType !== "form" && s.dialogType !== "step-form";
|
|
1294
2152
|
return import_lit2.html`
|
|
1295
2153
|
<div class="backdrop" ?data-open=${s.open} @click=${this._onBackdropClick}>
|
|
1296
|
-
<div class="card" ?data-closing=${this._isClosing}>
|
|
2154
|
+
<div class="card" data-type=${s.dialogType} ?data-closing=${this._isClosing}>
|
|
1297
2155
|
${showHeaderTitle ? import_lit2.html`<p class="dialog-title">${s.title}</p>` : import_lit2.nothing}
|
|
1298
2156
|
<div class="card-body">
|
|
1299
2157
|
${(0, import_keyed.keyed)(this._bodyKey, import_lit2.html`<div class="body-inner">${this._renderBody()}</div>`)}
|
|
@@ -1349,6 +2207,28 @@ var DialogSingleton = class {
|
|
|
1349
2207
|
__privateMethod(this, _DialogSingleton_instances, ensureElement_fn).call(this);
|
|
1350
2208
|
return __privateGet(this, _controller).confirm(optionsOrLabel);
|
|
1351
2209
|
}
|
|
2210
|
+
// ─── Form ──────────────────────────────────────────────────
|
|
2211
|
+
form(schema, options) {
|
|
2212
|
+
__privateMethod(this, _DialogSingleton_instances, ensureElement_fn).call(this);
|
|
2213
|
+
return __privateGet(this, _controller).form(schema, options);
|
|
2214
|
+
}
|
|
2215
|
+
// ─── Step Form ─────────────────────────────────────────────
|
|
2216
|
+
showStepForm(steps, options) {
|
|
2217
|
+
__privateMethod(this, _DialogSingleton_instances, ensureElement_fn).call(this);
|
|
2218
|
+
return __privateGet(this, _controller).showStepForm(steps, options);
|
|
2219
|
+
}
|
|
2220
|
+
onStepNext() {
|
|
2221
|
+
__privateGet(this, _controller).onStepNext();
|
|
2222
|
+
}
|
|
2223
|
+
onStepPrev() {
|
|
2224
|
+
__privateGet(this, _controller).onStepPrev();
|
|
2225
|
+
}
|
|
2226
|
+
updateStepFormField(fieldKey, value) {
|
|
2227
|
+
__privateGet(this, _controller).updateStepFormField(fieldKey, value);
|
|
2228
|
+
}
|
|
2229
|
+
touchStepFormField(fieldKey) {
|
|
2230
|
+
__privateGet(this, _controller).touchStepFormField(fieldKey);
|
|
2231
|
+
}
|
|
1352
2232
|
// ─── Loading helpers ─────────────────────────────────────
|
|
1353
2233
|
showLoading(label) {
|
|
1354
2234
|
__privateMethod(this, _DialogSingleton_instances, ensureElement_fn).call(this);
|