@enerjisaformlibrary/formbuilder-react 1.0.8 → 1.0.22
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +486 -27
- package/index.cjs +469 -240
- package/index.cjs.map +1 -1
- package/index.js +469 -240
- package/index.js.map +1 -1
- package/package.json +14 -19
- package/styles.css +1 -1
- package/types/client/src/components/form-builder/CanvasField.d.ts.map +1 -1
- package/types/client/src/components/form-builder/PropertiesPanel.d.ts.map +1 -1
- package/types/client/src/components/form-builder/Toolbar.d.ts.map +1 -1
- package/types/client/src/store/formStore.d.ts.map +1 -1
package/index.cjs
CHANGED
|
@@ -8124,6 +8124,25 @@ const AlignLeft = createLucideIcon("AlignLeft", [
|
|
|
8124
8124
|
*/
|
|
8125
8125
|
|
|
8126
8126
|
|
|
8127
|
+
const BookOpen = createLucideIcon("BookOpen", [
|
|
8128
|
+
["path", { d: "M12 7v14", key: "1akyts" }],
|
|
8129
|
+
[
|
|
8130
|
+
"path",
|
|
8131
|
+
{
|
|
8132
|
+
d: "M3 18a1 1 0 0 1-1-1V4a1 1 0 0 1 1-1h5a4 4 0 0 1 4 4 4 4 0 0 1 4-4h5a1 1 0 0 1 1 1v13a1 1 0 0 1-1 1h-6a3 3 0 0 0-3 3 3 3 0 0 0-3-3z",
|
|
8133
|
+
key: "ruj8y"
|
|
8134
|
+
}
|
|
8135
|
+
]
|
|
8136
|
+
]);
|
|
8137
|
+
|
|
8138
|
+
/**
|
|
8139
|
+
* @license lucide-react v0.453.0 - ISC
|
|
8140
|
+
*
|
|
8141
|
+
* This source code is licensed under the ISC license.
|
|
8142
|
+
* See the LICENSE file in the root directory of this source tree.
|
|
8143
|
+
*/
|
|
8144
|
+
|
|
8145
|
+
|
|
8127
8146
|
const Box = createLucideIcon("Box", [
|
|
8128
8147
|
[
|
|
8129
8148
|
"path",
|
|
@@ -9434,16 +9453,26 @@ const createEmptyForm = () => ({
|
|
|
9434
9453
|
createdAt: new Date().toISOString(),
|
|
9435
9454
|
updatedAt: new Date().toISOString(),
|
|
9436
9455
|
});
|
|
9456
|
+
const MAX_HISTORY = 50;
|
|
9457
|
+
const pushToHistory = (state) => {
|
|
9458
|
+
const newHistory = state.history.slice(0, state.historyIndex + 1);
|
|
9459
|
+
newHistory.push(JSON.parse(JSON.stringify(state.form)));
|
|
9460
|
+
if (newHistory.length > MAX_HISTORY) {
|
|
9461
|
+
newHistory.shift();
|
|
9462
|
+
}
|
|
9463
|
+
return { history: newHistory, historyIndex: newHistory.length - 1 };
|
|
9464
|
+
};
|
|
9465
|
+
const initialForm = createDemoForm();
|
|
9437
9466
|
const useFormStore = create((set, get) => ({
|
|
9438
|
-
form:
|
|
9467
|
+
form: initialForm,
|
|
9439
9468
|
selection: { type: null },
|
|
9440
9469
|
isPreviewMode: false,
|
|
9441
9470
|
currentStepIndex: 0,
|
|
9442
9471
|
currentLanguage: 'en',
|
|
9443
9472
|
formValues: {},
|
|
9444
9473
|
canvasWidth: 'full',
|
|
9445
|
-
history: [],
|
|
9446
|
-
historyIndex:
|
|
9474
|
+
history: [JSON.parse(JSON.stringify(initialForm))],
|
|
9475
|
+
historyIndex: 0,
|
|
9447
9476
|
setCanvasWidth: (width) => set({ canvasWidth: width }),
|
|
9448
9477
|
undo: () => {
|
|
9449
9478
|
const state = get();
|
|
@@ -9480,75 +9509,87 @@ const useFormStore = create((set, get) => ({
|
|
|
9480
9509
|
selection: { type: null },
|
|
9481
9510
|
formValues: {},
|
|
9482
9511
|
})),
|
|
9483
|
-
clearForm: () =>
|
|
9484
|
-
|
|
9485
|
-
|
|
9486
|
-
|
|
9487
|
-
|
|
9488
|
-
|
|
9512
|
+
clearForm: () => {
|
|
9513
|
+
const newForm = createEmptyForm();
|
|
9514
|
+
return set({
|
|
9515
|
+
form: newForm,
|
|
9516
|
+
selection: { type: null },
|
|
9517
|
+
currentStepIndex: 0,
|
|
9518
|
+
formValues: {},
|
|
9519
|
+
history: [JSON.parse(JSON.stringify(newForm))],
|
|
9520
|
+
historyIndex: 0,
|
|
9521
|
+
});
|
|
9522
|
+
},
|
|
9489
9523
|
loadForm: (form) => set({
|
|
9490
9524
|
form,
|
|
9491
9525
|
selection: { type: null },
|
|
9492
9526
|
currentStepIndex: 0,
|
|
9493
9527
|
formValues: {},
|
|
9528
|
+
history: [JSON.parse(JSON.stringify(form))],
|
|
9529
|
+
historyIndex: 0,
|
|
9494
9530
|
}),
|
|
9495
9531
|
addRow: (columns = 1, stepId) => set((state) => {
|
|
9496
9532
|
const newRow = createEmptyRow(columns);
|
|
9533
|
+
let newForm;
|
|
9497
9534
|
if (state.form.isMultiStep && state.form.steps?.length) {
|
|
9498
9535
|
const targetStepId = stepId || state.form.steps[state.currentStepIndex]?.id;
|
|
9499
|
-
|
|
9500
|
-
form
|
|
9501
|
-
|
|
9502
|
-
|
|
9503
|
-
updatedAt: new Date().toISOString(),
|
|
9504
|
-
},
|
|
9536
|
+
newForm = {
|
|
9537
|
+
...state.form,
|
|
9538
|
+
steps: state.form.steps.map(s => s.id === targetStepId ? { ...s, rows: [...s.rows, newRow] } : s),
|
|
9539
|
+
updatedAt: new Date().toISOString(),
|
|
9505
9540
|
};
|
|
9506
9541
|
}
|
|
9507
|
-
|
|
9508
|
-
|
|
9542
|
+
else {
|
|
9543
|
+
newForm = {
|
|
9509
9544
|
...state.form,
|
|
9510
9545
|
rows: [...state.form.rows, newRow],
|
|
9511
9546
|
updatedAt: new Date().toISOString(),
|
|
9512
|
-
}
|
|
9513
|
-
}
|
|
9547
|
+
};
|
|
9548
|
+
}
|
|
9549
|
+
const historyUpdate = pushToHistory({ form: newForm, history: state.history, historyIndex: state.historyIndex });
|
|
9550
|
+
return { form: newForm, ...historyUpdate };
|
|
9514
9551
|
}),
|
|
9515
9552
|
updateRow: (rowId, updates) => set((state) => {
|
|
9516
9553
|
const updateRows = (rows) => rows.map((row) => (row.id === rowId ? { ...row, ...updates } : row));
|
|
9554
|
+
let newForm;
|
|
9517
9555
|
if (state.form.isMultiStep && state.form.steps?.length) {
|
|
9518
|
-
|
|
9519
|
-
form
|
|
9520
|
-
|
|
9521
|
-
|
|
9522
|
-
updatedAt: new Date().toISOString(),
|
|
9523
|
-
},
|
|
9556
|
+
newForm = {
|
|
9557
|
+
...state.form,
|
|
9558
|
+
steps: state.form.steps.map(s => ({ ...s, rows: updateRows(s.rows) })),
|
|
9559
|
+
updatedAt: new Date().toISOString(),
|
|
9524
9560
|
};
|
|
9525
9561
|
}
|
|
9526
|
-
|
|
9527
|
-
|
|
9562
|
+
else {
|
|
9563
|
+
newForm = {
|
|
9528
9564
|
...state.form,
|
|
9529
9565
|
rows: updateRows(state.form.rows),
|
|
9530
9566
|
updatedAt: new Date().toISOString(),
|
|
9531
|
-
}
|
|
9532
|
-
}
|
|
9567
|
+
};
|
|
9568
|
+
}
|
|
9569
|
+
const historyUpdate = pushToHistory({ form: newForm, history: state.history, historyIndex: state.historyIndex });
|
|
9570
|
+
return { form: newForm, ...historyUpdate };
|
|
9533
9571
|
}),
|
|
9534
9572
|
deleteRow: (rowId) => set((state) => {
|
|
9535
9573
|
const filterRows = (rows) => rows.filter((row) => row.id !== rowId);
|
|
9574
|
+
let newForm;
|
|
9536
9575
|
if (state.form.isMultiStep && state.form.steps?.length) {
|
|
9537
|
-
|
|
9538
|
-
form
|
|
9539
|
-
|
|
9540
|
-
|
|
9541
|
-
updatedAt: new Date().toISOString(),
|
|
9542
|
-
},
|
|
9543
|
-
selection: state.selection.rowId === rowId ? { type: null } : state.selection,
|
|
9576
|
+
newForm = {
|
|
9577
|
+
...state.form,
|
|
9578
|
+
steps: state.form.steps.map(s => ({ ...s, rows: filterRows(s.rows) })),
|
|
9579
|
+
updatedAt: new Date().toISOString(),
|
|
9544
9580
|
};
|
|
9545
9581
|
}
|
|
9546
|
-
|
|
9547
|
-
|
|
9582
|
+
else {
|
|
9583
|
+
newForm = {
|
|
9548
9584
|
...state.form,
|
|
9549
9585
|
rows: filterRows(state.form.rows),
|
|
9550
9586
|
updatedAt: new Date().toISOString(),
|
|
9551
|
-
}
|
|
9587
|
+
};
|
|
9588
|
+
}
|
|
9589
|
+
const historyUpdate = pushToHistory({ form: newForm, history: state.history, historyIndex: state.historyIndex });
|
|
9590
|
+
return {
|
|
9591
|
+
form: newForm,
|
|
9592
|
+
...historyUpdate,
|
|
9552
9593
|
selection: state.selection.rowId === rowId ? { type: null } : state.selection,
|
|
9553
9594
|
};
|
|
9554
9595
|
}),
|
|
@@ -9559,18 +9600,19 @@ const useFormStore = create((set, get) => ({
|
|
|
9559
9600
|
newRows.splice(toIndex, 0, removed);
|
|
9560
9601
|
return newRows;
|
|
9561
9602
|
};
|
|
9603
|
+
let newForm;
|
|
9562
9604
|
if (state.form.isMultiStep && stepId) {
|
|
9563
|
-
|
|
9564
|
-
form
|
|
9565
|
-
|
|
9566
|
-
|
|
9567
|
-
updatedAt: new Date().toISOString(),
|
|
9568
|
-
},
|
|
9605
|
+
newForm = {
|
|
9606
|
+
...state.form,
|
|
9607
|
+
steps: state.form.steps?.map(s => s.id === stepId ? { ...s, rows: moveInRows(s.rows) } : s),
|
|
9608
|
+
updatedAt: new Date().toISOString(),
|
|
9569
9609
|
};
|
|
9570
9610
|
}
|
|
9571
|
-
|
|
9572
|
-
|
|
9573
|
-
}
|
|
9611
|
+
else {
|
|
9612
|
+
newForm = { ...state.form, rows: moveInRows(state.form.rows), updatedAt: new Date().toISOString() };
|
|
9613
|
+
}
|
|
9614
|
+
const historyUpdate = pushToHistory({ form: newForm, history: state.history, historyIndex: state.historyIndex });
|
|
9615
|
+
return { form: newForm, ...historyUpdate };
|
|
9574
9616
|
}),
|
|
9575
9617
|
addColumn: (rowId) => set((state) => {
|
|
9576
9618
|
const updateRows = (rows) => rows.map((row) => {
|
|
@@ -9586,22 +9628,23 @@ const useFormStore = create((set, get) => ({
|
|
|
9586
9628
|
],
|
|
9587
9629
|
};
|
|
9588
9630
|
});
|
|
9631
|
+
let newForm;
|
|
9589
9632
|
if (state.form.isMultiStep && state.form.steps?.length) {
|
|
9590
|
-
|
|
9591
|
-
form
|
|
9592
|
-
|
|
9593
|
-
|
|
9594
|
-
updatedAt: new Date().toISOString(),
|
|
9595
|
-
},
|
|
9633
|
+
newForm = {
|
|
9634
|
+
...state.form,
|
|
9635
|
+
steps: state.form.steps.map(s => ({ ...s, rows: updateRows(s.rows) })),
|
|
9636
|
+
updatedAt: new Date().toISOString(),
|
|
9596
9637
|
};
|
|
9597
9638
|
}
|
|
9598
|
-
|
|
9599
|
-
|
|
9639
|
+
else {
|
|
9640
|
+
newForm = {
|
|
9600
9641
|
...state.form,
|
|
9601
9642
|
rows: updateRows(state.form.rows),
|
|
9602
9643
|
updatedAt: new Date().toISOString(),
|
|
9603
|
-
}
|
|
9604
|
-
}
|
|
9644
|
+
};
|
|
9645
|
+
}
|
|
9646
|
+
const historyUpdate = pushToHistory({ form: newForm, history: state.history, historyIndex: state.historyIndex });
|
|
9647
|
+
return { form: newForm, ...historyUpdate };
|
|
9605
9648
|
}),
|
|
9606
9649
|
updateColumn: (rowId, columnId, updates) => set((state) => {
|
|
9607
9650
|
const updateRows = (rows) => rows.map((row) => row.id === rowId
|
|
@@ -9610,22 +9653,23 @@ const useFormStore = create((set, get) => ({
|
|
|
9610
9653
|
columns: row.columns.map((col) => col.id === columnId ? { ...col, ...updates } : col),
|
|
9611
9654
|
}
|
|
9612
9655
|
: row);
|
|
9656
|
+
let newForm;
|
|
9613
9657
|
if (state.form.isMultiStep && state.form.steps?.length) {
|
|
9614
|
-
|
|
9615
|
-
form
|
|
9616
|
-
|
|
9617
|
-
|
|
9618
|
-
updatedAt: new Date().toISOString(),
|
|
9619
|
-
},
|
|
9658
|
+
newForm = {
|
|
9659
|
+
...state.form,
|
|
9660
|
+
steps: state.form.steps.map(s => ({ ...s, rows: updateRows(s.rows) })),
|
|
9661
|
+
updatedAt: new Date().toISOString(),
|
|
9620
9662
|
};
|
|
9621
9663
|
}
|
|
9622
|
-
|
|
9623
|
-
|
|
9664
|
+
else {
|
|
9665
|
+
newForm = {
|
|
9624
9666
|
...state.form,
|
|
9625
9667
|
rows: updateRows(state.form.rows),
|
|
9626
9668
|
updatedAt: new Date().toISOString(),
|
|
9627
|
-
}
|
|
9628
|
-
}
|
|
9669
|
+
};
|
|
9670
|
+
}
|
|
9671
|
+
const historyUpdate = pushToHistory({ form: newForm, history: state.history, historyIndex: state.historyIndex });
|
|
9672
|
+
return { form: newForm, ...historyUpdate };
|
|
9629
9673
|
}),
|
|
9630
9674
|
deleteColumn: (rowId, columnId) => set((state) => {
|
|
9631
9675
|
const updateRows = (rows) => rows.map((row) => {
|
|
@@ -9640,22 +9684,25 @@ const useFormStore = create((set, get) => ({
|
|
|
9640
9684
|
columns: newColumns.map((col) => ({ ...col, width })),
|
|
9641
9685
|
};
|
|
9642
9686
|
});
|
|
9687
|
+
let newForm;
|
|
9643
9688
|
if (state.form.isMultiStep && state.form.steps?.length) {
|
|
9644
|
-
|
|
9645
|
-
form
|
|
9646
|
-
|
|
9647
|
-
|
|
9648
|
-
updatedAt: new Date().toISOString(),
|
|
9649
|
-
},
|
|
9650
|
-
selection: state.selection.columnId === columnId ? { type: null } : state.selection,
|
|
9689
|
+
newForm = {
|
|
9690
|
+
...state.form,
|
|
9691
|
+
steps: state.form.steps.map(s => ({ ...s, rows: updateRows(s.rows) })),
|
|
9692
|
+
updatedAt: new Date().toISOString(),
|
|
9651
9693
|
};
|
|
9652
9694
|
}
|
|
9653
|
-
|
|
9654
|
-
|
|
9695
|
+
else {
|
|
9696
|
+
newForm = {
|
|
9655
9697
|
...state.form,
|
|
9656
9698
|
rows: updateRows(state.form.rows),
|
|
9657
9699
|
updatedAt: new Date().toISOString(),
|
|
9658
|
-
}
|
|
9700
|
+
};
|
|
9701
|
+
}
|
|
9702
|
+
const historyUpdate = pushToHistory({ form: newForm, history: state.history, historyIndex: state.historyIndex });
|
|
9703
|
+
return {
|
|
9704
|
+
form: newForm,
|
|
9705
|
+
...historyUpdate,
|
|
9659
9706
|
selection: state.selection.columnId === columnId ? { type: null } : state.selection,
|
|
9660
9707
|
};
|
|
9661
9708
|
}),
|
|
@@ -9684,22 +9731,23 @@ const useFormStore = create((set, get) => ({
|
|
|
9684
9731
|
columns: newColumns.map((col) => ({ ...col, width })),
|
|
9685
9732
|
};
|
|
9686
9733
|
});
|
|
9734
|
+
let newForm;
|
|
9687
9735
|
if (state.form.isMultiStep && state.form.steps?.length) {
|
|
9688
|
-
|
|
9689
|
-
form
|
|
9690
|
-
|
|
9691
|
-
|
|
9692
|
-
updatedAt: new Date().toISOString(),
|
|
9693
|
-
},
|
|
9736
|
+
newForm = {
|
|
9737
|
+
...state.form,
|
|
9738
|
+
steps: state.form.steps.map(s => ({ ...s, rows: updateRows(s.rows) })),
|
|
9739
|
+
updatedAt: new Date().toISOString(),
|
|
9694
9740
|
};
|
|
9695
9741
|
}
|
|
9696
|
-
|
|
9697
|
-
|
|
9742
|
+
else {
|
|
9743
|
+
newForm = {
|
|
9698
9744
|
...state.form,
|
|
9699
9745
|
rows: updateRows(state.form.rows),
|
|
9700
9746
|
updatedAt: new Date().toISOString(),
|
|
9701
|
-
}
|
|
9702
|
-
}
|
|
9747
|
+
};
|
|
9748
|
+
}
|
|
9749
|
+
const historyUpdate = pushToHistory({ form: newForm, history: state.history, historyIndex: state.historyIndex });
|
|
9750
|
+
return { form: newForm, ...historyUpdate };
|
|
9703
9751
|
}),
|
|
9704
9752
|
addField: (rowId, columnId, field) => set((state) => {
|
|
9705
9753
|
const updateRows = (rows) => rows.map((row) => row.id === rowId
|
|
@@ -9713,22 +9761,23 @@ const useFormStore = create((set, get) => ({
|
|
|
9713
9761
|
: col),
|
|
9714
9762
|
}
|
|
9715
9763
|
: row);
|
|
9764
|
+
let newForm;
|
|
9716
9765
|
if (state.form.isMultiStep && state.form.steps?.length) {
|
|
9717
|
-
|
|
9718
|
-
form
|
|
9719
|
-
|
|
9720
|
-
|
|
9721
|
-
updatedAt: new Date().toISOString(),
|
|
9722
|
-
},
|
|
9766
|
+
newForm = {
|
|
9767
|
+
...state.form,
|
|
9768
|
+
steps: state.form.steps.map(s => ({ ...s, rows: updateRows(s.rows) })),
|
|
9769
|
+
updatedAt: new Date().toISOString(),
|
|
9723
9770
|
};
|
|
9724
9771
|
}
|
|
9725
|
-
|
|
9726
|
-
|
|
9772
|
+
else {
|
|
9773
|
+
newForm = {
|
|
9727
9774
|
...state.form,
|
|
9728
9775
|
rows: updateRows(state.form.rows),
|
|
9729
9776
|
updatedAt: new Date().toISOString(),
|
|
9730
|
-
}
|
|
9731
|
-
}
|
|
9777
|
+
};
|
|
9778
|
+
}
|
|
9779
|
+
const historyUpdate = pushToHistory({ form: newForm, history: state.history, historyIndex: state.historyIndex });
|
|
9780
|
+
return { form: newForm, ...historyUpdate };
|
|
9732
9781
|
}),
|
|
9733
9782
|
addRowWithField: (field) => set((state) => {
|
|
9734
9783
|
const newRow = {
|
|
@@ -9739,25 +9788,26 @@ const useFormStore = create((set, get) => ({
|
|
|
9739
9788
|
fields: [{ ...field, id: nanoid() }],
|
|
9740
9789
|
}],
|
|
9741
9790
|
};
|
|
9791
|
+
let newForm;
|
|
9742
9792
|
if (state.form.isMultiStep && state.form.steps?.length) {
|
|
9743
9793
|
const currentStep = state.form.steps[state.currentStepIndex];
|
|
9744
|
-
|
|
9745
|
-
form
|
|
9746
|
-
|
|
9747
|
-
|
|
9748
|
-
|
|
9749
|
-
|
|
9750
|
-
updatedAt: new Date().toISOString(),
|
|
9751
|
-
},
|
|
9794
|
+
newForm = {
|
|
9795
|
+
...state.form,
|
|
9796
|
+
steps: state.form.steps.map(s => s.id === currentStep.id
|
|
9797
|
+
? { ...s, rows: [...s.rows, newRow] }
|
|
9798
|
+
: s),
|
|
9799
|
+
updatedAt: new Date().toISOString(),
|
|
9752
9800
|
};
|
|
9753
9801
|
}
|
|
9754
|
-
|
|
9755
|
-
|
|
9802
|
+
else {
|
|
9803
|
+
newForm = {
|
|
9756
9804
|
...state.form,
|
|
9757
9805
|
rows: [...state.form.rows, newRow],
|
|
9758
9806
|
updatedAt: new Date().toISOString(),
|
|
9759
|
-
}
|
|
9760
|
-
}
|
|
9807
|
+
};
|
|
9808
|
+
}
|
|
9809
|
+
const historyUpdate = pushToHistory({ form: newForm, history: state.history, historyIndex: state.historyIndex });
|
|
9810
|
+
return { form: newForm, ...historyUpdate };
|
|
9761
9811
|
}),
|
|
9762
9812
|
addFieldToContainerDirect: (rowId, columnId, containerFieldId, field) => set((state) => {
|
|
9763
9813
|
const newField = { ...field, id: nanoid() };
|
|
@@ -9783,22 +9833,23 @@ const useFormStore = create((set, get) => ({
|
|
|
9783
9833
|
: col),
|
|
9784
9834
|
}
|
|
9785
9835
|
: row);
|
|
9836
|
+
let newForm;
|
|
9786
9837
|
if (state.form.isMultiStep && state.form.steps?.length) {
|
|
9787
|
-
|
|
9788
|
-
form
|
|
9789
|
-
|
|
9790
|
-
|
|
9791
|
-
updatedAt: new Date().toISOString(),
|
|
9792
|
-
},
|
|
9838
|
+
newForm = {
|
|
9839
|
+
...state.form,
|
|
9840
|
+
steps: state.form.steps.map(s => ({ ...s, rows: updateRows(s.rows) })),
|
|
9841
|
+
updatedAt: new Date().toISOString(),
|
|
9793
9842
|
};
|
|
9794
9843
|
}
|
|
9795
|
-
|
|
9796
|
-
|
|
9844
|
+
else {
|
|
9845
|
+
newForm = {
|
|
9797
9846
|
...state.form,
|
|
9798
9847
|
rows: updateRows(state.form.rows),
|
|
9799
9848
|
updatedAt: new Date().toISOString(),
|
|
9800
|
-
}
|
|
9801
|
-
}
|
|
9849
|
+
};
|
|
9850
|
+
}
|
|
9851
|
+
const historyUpdate = pushToHistory({ form: newForm, history: state.history, historyIndex: state.historyIndex });
|
|
9852
|
+
return { form: newForm, ...historyUpdate };
|
|
9802
9853
|
}),
|
|
9803
9854
|
addFieldToContainer: (rowId, columnId, containerFieldId, containerRowId, containerColumnId, field) => set((state) => {
|
|
9804
9855
|
const newField = { ...field, id: nanoid() };
|
|
@@ -9834,22 +9885,23 @@ const useFormStore = create((set, get) => ({
|
|
|
9834
9885
|
: col),
|
|
9835
9886
|
}
|
|
9836
9887
|
: row);
|
|
9888
|
+
let newForm;
|
|
9837
9889
|
if (state.form.isMultiStep && state.form.steps?.length) {
|
|
9838
|
-
|
|
9839
|
-
form
|
|
9840
|
-
|
|
9841
|
-
|
|
9842
|
-
updatedAt: new Date().toISOString(),
|
|
9843
|
-
},
|
|
9890
|
+
newForm = {
|
|
9891
|
+
...state.form,
|
|
9892
|
+
steps: state.form.steps.map(s => ({ ...s, rows: updateRows(s.rows) })),
|
|
9893
|
+
updatedAt: new Date().toISOString(),
|
|
9844
9894
|
};
|
|
9845
9895
|
}
|
|
9846
|
-
|
|
9847
|
-
|
|
9896
|
+
else {
|
|
9897
|
+
newForm = {
|
|
9848
9898
|
...state.form,
|
|
9849
9899
|
rows: updateRows(state.form.rows),
|
|
9850
9900
|
updatedAt: new Date().toISOString(),
|
|
9851
|
-
}
|
|
9852
|
-
}
|
|
9901
|
+
};
|
|
9902
|
+
}
|
|
9903
|
+
const historyUpdate = pushToHistory({ form: newForm, history: state.history, historyIndex: state.historyIndex });
|
|
9904
|
+
return { form: newForm, ...historyUpdate };
|
|
9853
9905
|
}),
|
|
9854
9906
|
updateField: (rowId, columnId, fieldId, updates) => set((state) => {
|
|
9855
9907
|
const updateFieldInContainer = (field) => {
|
|
@@ -9914,22 +9966,23 @@ const useFormStore = create((set, get) => ({
|
|
|
9914
9966
|
: col),
|
|
9915
9967
|
}
|
|
9916
9968
|
: row);
|
|
9969
|
+
let newForm;
|
|
9917
9970
|
if (state.form.isMultiStep && state.form.steps?.length) {
|
|
9918
|
-
|
|
9919
|
-
form
|
|
9920
|
-
|
|
9921
|
-
|
|
9922
|
-
updatedAt: new Date().toISOString(),
|
|
9923
|
-
},
|
|
9971
|
+
newForm = {
|
|
9972
|
+
...state.form,
|
|
9973
|
+
steps: state.form.steps.map(s => ({ ...s, rows: updateRows(s.rows) })),
|
|
9974
|
+
updatedAt: new Date().toISOString(),
|
|
9924
9975
|
};
|
|
9925
9976
|
}
|
|
9926
|
-
|
|
9927
|
-
|
|
9977
|
+
else {
|
|
9978
|
+
newForm = {
|
|
9928
9979
|
...state.form,
|
|
9929
9980
|
rows: updateRows(state.form.rows),
|
|
9930
9981
|
updatedAt: new Date().toISOString(),
|
|
9931
|
-
}
|
|
9932
|
-
}
|
|
9982
|
+
};
|
|
9983
|
+
}
|
|
9984
|
+
const historyUpdate = pushToHistory({ form: newForm, history: state.history, historyIndex: state.historyIndex });
|
|
9985
|
+
return { form: newForm, ...historyUpdate };
|
|
9933
9986
|
}),
|
|
9934
9987
|
deleteField: (rowId, columnId, fieldId) => set((state) => {
|
|
9935
9988
|
const updateRows = (rows) => rows.map((row) => row.id === rowId
|
|
@@ -9960,22 +10013,25 @@ const useFormStore = create((set, get) => ({
|
|
|
9960
10013
|
: col),
|
|
9961
10014
|
}
|
|
9962
10015
|
: row);
|
|
10016
|
+
let newForm;
|
|
9963
10017
|
if (state.form.isMultiStep && state.form.steps?.length) {
|
|
9964
|
-
|
|
9965
|
-
form
|
|
9966
|
-
|
|
9967
|
-
|
|
9968
|
-
updatedAt: new Date().toISOString(),
|
|
9969
|
-
},
|
|
9970
|
-
selection: state.selection.fieldId === fieldId ? { type: null } : state.selection,
|
|
10018
|
+
newForm = {
|
|
10019
|
+
...state.form,
|
|
10020
|
+
steps: state.form.steps.map(s => ({ ...s, rows: updateRows(s.rows) })),
|
|
10021
|
+
updatedAt: new Date().toISOString(),
|
|
9971
10022
|
};
|
|
9972
10023
|
}
|
|
9973
|
-
|
|
9974
|
-
|
|
10024
|
+
else {
|
|
10025
|
+
newForm = {
|
|
9975
10026
|
...state.form,
|
|
9976
10027
|
rows: updateRows(state.form.rows),
|
|
9977
10028
|
updatedAt: new Date().toISOString(),
|
|
9978
|
-
}
|
|
10029
|
+
};
|
|
10030
|
+
}
|
|
10031
|
+
const historyUpdate = pushToHistory({ form: newForm, history: state.history, historyIndex: state.historyIndex });
|
|
10032
|
+
return {
|
|
10033
|
+
form: newForm,
|
|
10034
|
+
...historyUpdate,
|
|
9979
10035
|
selection: state.selection.fieldId === fieldId ? { type: null } : state.selection,
|
|
9980
10036
|
};
|
|
9981
10037
|
}),
|
|
@@ -10013,22 +10069,23 @@ const useFormStore = create((set, get) => ({
|
|
|
10013
10069
|
}
|
|
10014
10070
|
return row;
|
|
10015
10071
|
});
|
|
10072
|
+
let newForm;
|
|
10016
10073
|
if (state.form.isMultiStep && state.form.steps?.length) {
|
|
10017
10074
|
let newSteps = state.form.steps.map(s => ({ ...s, rows: extractField(s.rows) }));
|
|
10018
10075
|
if (!movedField)
|
|
10019
10076
|
return state;
|
|
10020
10077
|
newSteps = newSteps.map(s => ({ ...s, rows: insertField(s.rows) }));
|
|
10021
|
-
|
|
10022
|
-
form: { ...state.form, steps: newSteps, updatedAt: new Date().toISOString() },
|
|
10023
|
-
};
|
|
10078
|
+
newForm = { ...state.form, steps: newSteps, updatedAt: new Date().toISOString() };
|
|
10024
10079
|
}
|
|
10025
|
-
|
|
10026
|
-
|
|
10027
|
-
|
|
10028
|
-
|
|
10029
|
-
|
|
10030
|
-
|
|
10031
|
-
}
|
|
10080
|
+
else {
|
|
10081
|
+
const rows = extractField(state.form.rows);
|
|
10082
|
+
if (!movedField)
|
|
10083
|
+
return state;
|
|
10084
|
+
const finalRows = insertField(rows);
|
|
10085
|
+
newForm = { ...state.form, rows: finalRows, updatedAt: new Date().toISOString() };
|
|
10086
|
+
}
|
|
10087
|
+
const historyUpdate = pushToHistory({ form: newForm, history: state.history, historyIndex: state.historyIndex });
|
|
10088
|
+
return { form: newForm, ...historyUpdate };
|
|
10032
10089
|
}),
|
|
10033
10090
|
addStep: () => set((state) => {
|
|
10034
10091
|
const newStep = createEmptyStep(state.form.steps?.length || 0);
|
|
@@ -10041,22 +10098,27 @@ const useFormStore = create((set, get) => ({
|
|
|
10041
10098
|
},
|
|
10042
10099
|
};
|
|
10043
10100
|
}),
|
|
10044
|
-
updateStep: (stepId, updates) => set((state) =>
|
|
10045
|
-
|
|
10101
|
+
updateStep: (stepId, updates) => set((state) => {
|
|
10102
|
+
const newForm = {
|
|
10046
10103
|
...state.form,
|
|
10047
10104
|
steps: state.form.steps?.map(s => s.id === stepId ? { ...s, ...updates } : s),
|
|
10048
10105
|
updatedAt: new Date().toISOString(),
|
|
10049
|
-
}
|
|
10050
|
-
|
|
10106
|
+
};
|
|
10107
|
+
const historyUpdate = pushToHistory({ form: newForm, history: state.history, historyIndex: state.historyIndex });
|
|
10108
|
+
return { form: newForm, ...historyUpdate };
|
|
10109
|
+
}),
|
|
10051
10110
|
deleteStep: (stepId) => set((state) => {
|
|
10052
10111
|
const newSteps = state.form.steps?.filter(s => s.id !== stepId) || [];
|
|
10112
|
+
const newForm = {
|
|
10113
|
+
...state.form,
|
|
10114
|
+
steps: newSteps,
|
|
10115
|
+
isMultiStep: newSteps.length > 0,
|
|
10116
|
+
updatedAt: new Date().toISOString(),
|
|
10117
|
+
};
|
|
10118
|
+
const historyUpdate = pushToHistory({ form: newForm, history: state.history, historyIndex: state.historyIndex });
|
|
10053
10119
|
return {
|
|
10054
|
-
form:
|
|
10055
|
-
|
|
10056
|
-
steps: newSteps,
|
|
10057
|
-
isMultiStep: newSteps.length > 0,
|
|
10058
|
-
updatedAt: new Date().toISOString(),
|
|
10059
|
-
},
|
|
10120
|
+
form: newForm,
|
|
10121
|
+
...historyUpdate,
|
|
10060
10122
|
currentStepIndex: Math.min(state.currentStepIndex, Math.max(0, newSteps.length - 1)),
|
|
10061
10123
|
selection: state.selection.stepId === stepId ? { type: null } : state.selection,
|
|
10062
10124
|
};
|
|
@@ -10065,9 +10127,9 @@ const useFormStore = create((set, get) => ({
|
|
|
10065
10127
|
const steps = [...(state.form.steps || [])];
|
|
10066
10128
|
const [removed] = steps.splice(fromIndex, 1);
|
|
10067
10129
|
steps.splice(toIndex, 0, removed);
|
|
10068
|
-
|
|
10069
|
-
|
|
10070
|
-
};
|
|
10130
|
+
const newForm = { ...state.form, steps, updatedAt: new Date().toISOString() };
|
|
10131
|
+
const historyUpdate = pushToHistory({ form: newForm, history: state.history, historyIndex: state.historyIndex });
|
|
10132
|
+
return { form: newForm, ...historyUpdate };
|
|
10071
10133
|
}),
|
|
10072
10134
|
setCurrentStep: (index) => set((state) => ({
|
|
10073
10135
|
currentStepIndex: Math.max(0, Math.min(index, (state.form.steps?.length || 1) - 1)),
|
|
@@ -10079,33 +10141,30 @@ const useFormStore = create((set, get) => ({
|
|
|
10079
10141
|
currentStepIndex: Math.max(0, state.currentStepIndex - 1),
|
|
10080
10142
|
})),
|
|
10081
10143
|
toggleMultiStep: () => set((state) => {
|
|
10144
|
+
let newForm;
|
|
10082
10145
|
if (state.form.isMultiStep) {
|
|
10083
10146
|
const allRows = state.form.steps?.flatMap(s => s.rows) || [];
|
|
10084
|
-
|
|
10085
|
-
form
|
|
10086
|
-
|
|
10087
|
-
|
|
10088
|
-
|
|
10089
|
-
|
|
10090
|
-
updatedAt: new Date().toISOString(),
|
|
10091
|
-
},
|
|
10092
|
-
currentStepIndex: 0,
|
|
10147
|
+
newForm = {
|
|
10148
|
+
...state.form,
|
|
10149
|
+
isMultiStep: false,
|
|
10150
|
+
rows: [...state.form.rows, ...allRows],
|
|
10151
|
+
steps: [],
|
|
10152
|
+
updatedAt: new Date().toISOString(),
|
|
10093
10153
|
};
|
|
10094
10154
|
}
|
|
10095
10155
|
else {
|
|
10096
10156
|
const step = createEmptyStep(0);
|
|
10097
10157
|
step.rows = [...state.form.rows];
|
|
10098
|
-
|
|
10099
|
-
form
|
|
10100
|
-
|
|
10101
|
-
|
|
10102
|
-
|
|
10103
|
-
|
|
10104
|
-
updatedAt: new Date().toISOString(),
|
|
10105
|
-
},
|
|
10106
|
-
currentStepIndex: 0,
|
|
10158
|
+
newForm = {
|
|
10159
|
+
...state.form,
|
|
10160
|
+
isMultiStep: true,
|
|
10161
|
+
rows: [],
|
|
10162
|
+
steps: [step],
|
|
10163
|
+
updatedAt: new Date().toISOString(),
|
|
10107
10164
|
};
|
|
10108
10165
|
}
|
|
10166
|
+
const historyUpdate = pushToHistory({ form: newForm, history: state.history, historyIndex: state.historyIndex });
|
|
10167
|
+
return { form: newForm, ...historyUpdate, currentStepIndex: 0 };
|
|
10109
10168
|
}),
|
|
10110
10169
|
updateSubmissionConfig: (config) => set((state) => ({
|
|
10111
10170
|
form: {
|
|
@@ -18604,7 +18663,7 @@ function MultiSelectField({ value, onChange, options, disabled, maxItems, classN
|
|
|
18604
18663
|
}
|
|
18605
18664
|
function CanvasField({ field, rowId, columnId, isPreviewMode: externalPreviewMode, getFieldValue: externalGetFieldValue, setFieldValue: externalSetFieldValue, isInsideContainer = false, fieldSize = 'normal' }) {
|
|
18606
18665
|
const store = useFormStore();
|
|
18607
|
-
const { selection, setSelection, deleteField, evaluateCondition, clearFormValues } = store;
|
|
18666
|
+
const { selection, setSelection, deleteField, evaluateCondition, clearFormValues, formValues } = store;
|
|
18608
18667
|
const isPreviewMode = externalPreviewMode ?? store.isPreviewMode;
|
|
18609
18668
|
const getFieldValue = externalGetFieldValue ?? store.getFieldValue;
|
|
18610
18669
|
const setFieldValue = externalSetFieldValue ?? store.setFieldValue;
|
|
@@ -18628,6 +18687,15 @@ function CanvasField({ field, rowId, columnId, isPreviewMode: externalPreviewMod
|
|
|
18628
18687
|
// Reset rating, slider values
|
|
18629
18688
|
setRatingValue(field.props.defaultValue ? parseInt(field.props.defaultValue) || 0 : 0);
|
|
18630
18689
|
setSliderValue([field.props.defaultValue ? parseInt(field.props.defaultValue) || 50 : 50]);
|
|
18690
|
+
// Auto focus when entering preview mode
|
|
18691
|
+
if (field.props.autoFocus) {
|
|
18692
|
+
setTimeout(() => {
|
|
18693
|
+
const input = document.querySelector(`[data-testid^="field-"][data-testid$="-${field.id}"]`);
|
|
18694
|
+
if (input && input.focus) {
|
|
18695
|
+
input.focus();
|
|
18696
|
+
}
|
|
18697
|
+
}, 100);
|
|
18698
|
+
}
|
|
18631
18699
|
}
|
|
18632
18700
|
}, [isPreviewMode]);
|
|
18633
18701
|
const isSelected = selection.type === 'field' &&
|
|
@@ -18660,8 +18728,59 @@ function CanvasField({ field, rowId, columnId, isPreviewMode: externalPreviewMod
|
|
|
18660
18728
|
break;
|
|
18661
18729
|
}
|
|
18662
18730
|
return { visible, enabled, required };
|
|
18663
|
-
}, [field.conditionalLogic, field.validation?.required, evaluateCondition]);
|
|
18664
|
-
|
|
18731
|
+
}, [field.conditionalLogic, field.validation?.required, evaluateCondition, formValues]);
|
|
18732
|
+
const handleChange = React.useCallback((newValue) => {
|
|
18733
|
+
setLocalValue(newValue);
|
|
18734
|
+
setFieldValue(field.props.key, newValue);
|
|
18735
|
+
if (touched) {
|
|
18736
|
+
setError(validateField(newValue, field.validation, field.type));
|
|
18737
|
+
}
|
|
18738
|
+
}, [touched, field.validation, field.type, field.props.key, setFieldValue]);
|
|
18739
|
+
const handleBlur = React.useCallback(() => {
|
|
18740
|
+
setTouched(true);
|
|
18741
|
+
setError(validateField(localValue, field.validation, field.type));
|
|
18742
|
+
}, [localValue, field.validation, field.type]);
|
|
18743
|
+
// Execute field actions (onClick, onChange, onFocus, onBlur events)
|
|
18744
|
+
const executeActions = React.useCallback((eventType) => {
|
|
18745
|
+
if (!isPreviewMode || !field.events)
|
|
18746
|
+
return;
|
|
18747
|
+
const actions = field.events[eventType];
|
|
18748
|
+
if (!actions || actions.length === 0)
|
|
18749
|
+
return;
|
|
18750
|
+
actions.forEach((action) => {
|
|
18751
|
+
if (action.type === 'common') {
|
|
18752
|
+
switch (action.name) {
|
|
18753
|
+
case 'focusField':
|
|
18754
|
+
if (action.args?.targetFieldKey) {
|
|
18755
|
+
setTimeout(() => {
|
|
18756
|
+
const allInputs = document.querySelectorAll('[data-field-key]');
|
|
18757
|
+
allInputs.forEach((el) => {
|
|
18758
|
+
if (el.getAttribute('data-field-key') === action.args?.targetFieldKey) {
|
|
18759
|
+
el.focus();
|
|
18760
|
+
}
|
|
18761
|
+
});
|
|
18762
|
+
}, 50);
|
|
18763
|
+
}
|
|
18764
|
+
break;
|
|
18765
|
+
case 'clearField':
|
|
18766
|
+
setLocalValue('');
|
|
18767
|
+
setFieldValue(field.props.key, '');
|
|
18768
|
+
break;
|
|
18769
|
+
case 'showMessage':
|
|
18770
|
+
if (action.args?.message) {
|
|
18771
|
+
alert(action.args.message);
|
|
18772
|
+
}
|
|
18773
|
+
break;
|
|
18774
|
+
case 'reset':
|
|
18775
|
+
clearFormValues();
|
|
18776
|
+
break;
|
|
18777
|
+
}
|
|
18778
|
+
}
|
|
18779
|
+
});
|
|
18780
|
+
}, [isPreviewMode, field.events, field.props.key, setFieldValue, clearFormValues]);
|
|
18781
|
+
// Early return for hidden fields - MUST be after all hooks
|
|
18782
|
+
// Check both conditional visibility AND explicit hidden property
|
|
18783
|
+
if (isPreviewMode && (!conditionalState.visible || field.props.hidden)) {
|
|
18665
18784
|
return null;
|
|
18666
18785
|
}
|
|
18667
18786
|
const isFieldDisabled = field.props.disabled || !isPreviewMode || !conditionalState.enabled;
|
|
@@ -18676,18 +18795,10 @@ function CanvasField({ field, rowId, columnId, isPreviewMode: externalPreviewMod
|
|
|
18676
18795
|
fieldId: field.id,
|
|
18677
18796
|
});
|
|
18678
18797
|
}
|
|
18679
|
-
|
|
18680
|
-
|
|
18681
|
-
setLocalValue(newValue);
|
|
18682
|
-
setFieldValue(field.props.key, newValue);
|
|
18683
|
-
if (touched) {
|
|
18684
|
-
setError(validateField(newValue, field.validation, field.type));
|
|
18798
|
+
else {
|
|
18799
|
+
executeActions('onClick');
|
|
18685
18800
|
}
|
|
18686
|
-
}
|
|
18687
|
-
const handleBlur = React.useCallback(() => {
|
|
18688
|
-
setTouched(true);
|
|
18689
|
-
setError(validateField(localValue, field.validation, field.type));
|
|
18690
|
-
}, [localValue, field.validation, field.type]);
|
|
18801
|
+
};
|
|
18691
18802
|
const sizeClasses = {
|
|
18692
18803
|
small: 'h-8 text-sm',
|
|
18693
18804
|
medium: 'h-9',
|
|
@@ -18710,51 +18821,51 @@ function CanvasField({ field, rowId, columnId, isPreviewMode: externalPreviewMod
|
|
|
18710
18821
|
const errorClass = hasError ? 'border-destructive focus-visible:ring-destructive' : '';
|
|
18711
18822
|
switch (field.type) {
|
|
18712
18823
|
case 'input':
|
|
18713
|
-
return (jsxRuntime.jsx(Input, { placeholder: field.props.placeholder, disabled: isFieldDisabled, readOnly: field.props.readOnly, value: isPreviewMode ? localValue : (field.props.defaultValue || ''), onChange: (e) => isPreviewMode && handleChange(e.target.value), onBlur: handleBlur, tabIndex: tabIndexValue, className: `${inputSize} ${errorClass} ${field.customStyle?.inputClassName || ''}`, style: {
|
|
18824
|
+
return (jsxRuntime.jsx(Input, { placeholder: field.props.placeholder, disabled: isFieldDisabled, readOnly: field.props.readOnly, autoFocus: isPreviewMode && field.props.autoFocus, value: isPreviewMode ? localValue : (field.props.defaultValue || ''), onChange: (e) => isPreviewMode && handleChange(e.target.value), onBlur: handleBlur, tabIndex: tabIndexValue, className: `${inputSize} ${errorClass} ${field.customStyle?.inputClassName || ''}`, style: {
|
|
18714
18825
|
...(field.customStyle?.color ? { color: field.customStyle.color } : {}),
|
|
18715
18826
|
...(field.customStyle?.backgroundColor ? { backgroundColor: field.customStyle.backgroundColor } : {}),
|
|
18716
|
-
}, "data-testid": `field-input-${field.id}
|
|
18827
|
+
}, "data-testid": `field-input-${field.id}`, "data-field-key": field.props.key }));
|
|
18717
18828
|
case 'password':
|
|
18718
|
-
return (jsxRuntime.jsx(Input, { type: "password", placeholder: field.props.placeholder, disabled: isFieldDisabled, value: isPreviewMode ? localValue : '', onChange: (e) => isPreviewMode && handleChange(e.target.value), onBlur: handleBlur, tabIndex: tabIndexValue, className: `${inputSize} ${errorClass} ${field.customStyle?.inputClassName || ''}`, style: {
|
|
18829
|
+
return (jsxRuntime.jsx(Input, { type: "password", placeholder: field.props.placeholder, disabled: isFieldDisabled, autoFocus: isPreviewMode && field.props.autoFocus, value: isPreviewMode ? localValue : '', onChange: (e) => isPreviewMode && handleChange(e.target.value), onBlur: handleBlur, tabIndex: tabIndexValue, className: `${inputSize} ${errorClass} ${field.customStyle?.inputClassName || ''}`, style: {
|
|
18719
18830
|
...(field.customStyle?.color ? { color: field.customStyle.color } : {}),
|
|
18720
18831
|
...(field.customStyle?.backgroundColor ? { backgroundColor: field.customStyle.backgroundColor } : {}),
|
|
18721
|
-
}, "data-testid": `field-password-${field.id}
|
|
18832
|
+
}, "data-testid": `field-password-${field.id}`, "data-field-key": field.props.key }));
|
|
18722
18833
|
case 'phone':
|
|
18723
|
-
return (jsxRuntime.jsx(Input, { type: "tel", placeholder: field.props.placeholder || '+1 (555) 000-0000', disabled: isFieldDisabled, value: isPreviewMode ? localValue : (field.props.defaultValue || ''), onChange: (e) => isPreviewMode && handleChange(e.target.value), onBlur: handleBlur, tabIndex: tabIndexValue, className: `${inputSize} ${errorClass} ${field.customStyle?.inputClassName || ''}`, style: {
|
|
18834
|
+
return (jsxRuntime.jsx(Input, { type: "tel", placeholder: field.props.placeholder || '+1 (555) 000-0000', disabled: isFieldDisabled, autoFocus: isPreviewMode && field.props.autoFocus, "data-field-key": field.props.key, value: isPreviewMode ? localValue : (field.props.defaultValue || ''), onChange: (e) => isPreviewMode && handleChange(e.target.value), onBlur: handleBlur, tabIndex: tabIndexValue, className: `${inputSize} ${errorClass} ${field.customStyle?.inputClassName || ''}`, style: {
|
|
18724
18835
|
...(field.customStyle?.color ? { color: field.customStyle.color } : {}),
|
|
18725
18836
|
...(field.customStyle?.backgroundColor ? { backgroundColor: field.customStyle.backgroundColor } : {}),
|
|
18726
18837
|
}, "data-testid": `field-phone-${field.id}` }));
|
|
18727
18838
|
case 'url':
|
|
18728
|
-
return (jsxRuntime.jsx(Input, { type: "url", placeholder: field.props.placeholder || 'https://example.com', disabled: isFieldDisabled, value: isPreviewMode ? localValue : (field.props.defaultValue || ''), onChange: (e) => isPreviewMode && handleChange(e.target.value), onBlur: handleBlur, tabIndex: tabIndexValue, className: `${inputSize} ${errorClass} ${field.customStyle?.inputClassName || ''}`, style: {
|
|
18839
|
+
return (jsxRuntime.jsx(Input, { type: "url", placeholder: field.props.placeholder || 'https://example.com', disabled: isFieldDisabled, autoFocus: isPreviewMode && field.props.autoFocus, value: isPreviewMode ? localValue : (field.props.defaultValue || ''), onChange: (e) => isPreviewMode && handleChange(e.target.value), onBlur: handleBlur, tabIndex: tabIndexValue, className: `${inputSize} ${errorClass} ${field.customStyle?.inputClassName || ''}`, style: {
|
|
18729
18840
|
...(field.customStyle?.color ? { color: field.customStyle.color } : {}),
|
|
18730
18841
|
...(field.customStyle?.backgroundColor ? { backgroundColor: field.customStyle.backgroundColor } : {}),
|
|
18731
|
-
}, "data-testid": `field-url-${field.id}
|
|
18842
|
+
}, "data-testid": `field-url-${field.id}`, "data-field-key": field.props.key }));
|
|
18732
18843
|
case 'textarea':
|
|
18733
|
-
return (jsxRuntime.jsx(Textarea, { placeholder: field.props.placeholder, disabled: isFieldDisabled, readOnly: field.props.readOnly, value: isPreviewMode ? localValue : (field.props.defaultValue || ''), onChange: (e) => isPreviewMode && handleChange(e.target.value), onBlur: handleBlur, tabIndex: tabIndexValue, className: `min-h-[80px] ${errorClass} ${field.customStyle?.inputClassName || ''}`, style: {
|
|
18844
|
+
return (jsxRuntime.jsx(Textarea, { placeholder: field.props.placeholder, disabled: isFieldDisabled, readOnly: field.props.readOnly, autoFocus: isPreviewMode && field.props.autoFocus, value: isPreviewMode ? localValue : (field.props.defaultValue || ''), onChange: (e) => isPreviewMode && handleChange(e.target.value), onBlur: handleBlur, tabIndex: tabIndexValue, className: `min-h-[80px] ${errorClass} ${field.customStyle?.inputClassName || ''}`, style: {
|
|
18734
18845
|
...(field.customStyle?.color ? { color: field.customStyle.color } : {}),
|
|
18735
18846
|
...(field.customStyle?.backgroundColor ? { backgroundColor: field.customStyle.backgroundColor } : {}),
|
|
18736
|
-
}, "data-testid": `field-textarea-${field.id}
|
|
18847
|
+
}, "data-testid": `field-textarea-${field.id}`, "data-field-key": field.props.key }));
|
|
18737
18848
|
case 'dropdown':
|
|
18738
18849
|
const dropdownOptions = typeof field.props.optionsString === 'string'
|
|
18739
18850
|
? field.props.optionsString.split('\n').filter((o) => o.trim())
|
|
18740
18851
|
: (field.props.optionsString || []);
|
|
18741
|
-
return (jsxRuntime.jsxs(Select, { disabled: isFieldDisabled, value: isPreviewMode ? localValue : undefined, onValueChange: (v) => isPreviewMode && handleChange(v), children: [jsxRuntime.jsx(SelectTrigger, { className: `${inputSize} ${errorClass} ${field.customStyle?.inputClassName || ''}`, style: {
|
|
18852
|
+
return (jsxRuntime.jsxs(Select, { disabled: isFieldDisabled, value: isPreviewMode ? localValue : undefined, onValueChange: (v) => isPreviewMode && handleChange(v), children: [jsxRuntime.jsx(SelectTrigger, { className: `${inputSize} ${errorClass} ${field.customStyle?.inputClassName || ''}`, tabIndex: tabIndexValue, style: {
|
|
18742
18853
|
...(field.customStyle?.color ? { color: field.customStyle.color } : {}),
|
|
18743
18854
|
...(field.customStyle?.backgroundColor ? { backgroundColor: field.customStyle.backgroundColor } : {}),
|
|
18744
18855
|
}, "data-testid": `field-dropdown-${field.id}`, children: jsxRuntime.jsx(SelectValue, { placeholder: field.props.placeholder || 'Select...' }) }), jsxRuntime.jsx(SelectContent, { children: dropdownOptions.map((option, i) => (jsxRuntime.jsx(SelectItem, { value: option, children: option }, i))) })] }));
|
|
18745
18856
|
case 'checkbox':
|
|
18746
|
-
return (jsxRuntime.jsxs("div", { className: `flex items-center gap-2 ${field.customStyle?.inputClassName || ''}`, children: [jsxRuntime.jsx(Checkbox, { disabled: isFieldDisabled, "data-testid": `field-checkbox-${field.id}` }), jsxRuntime.jsx("span", { className: "text-sm text-foreground", style: {
|
|
18857
|
+
return (jsxRuntime.jsxs("div", { className: `flex items-center gap-2 ${field.customStyle?.inputClassName || ''}`, children: [jsxRuntime.jsx(Checkbox, { disabled: isFieldDisabled, tabIndex: tabIndexValue, "data-testid": `field-checkbox-${field.id}` }), jsxRuntime.jsx("span", { className: "text-sm text-foreground", style: {
|
|
18747
18858
|
...(field.customStyle?.color ? { color: field.customStyle.color } : {}),
|
|
18748
18859
|
}, children: field.props.label })] }));
|
|
18749
18860
|
case 'radio':
|
|
18750
18861
|
const radioOptions = typeof field.props.optionsString === 'string'
|
|
18751
18862
|
? field.props.optionsString.split('\n').filter((o) => o.trim())
|
|
18752
18863
|
: (field.props.optionsString || []);
|
|
18753
|
-
return (jsxRuntime.jsx(RadioGroup$1, { disabled: isFieldDisabled, className: field.customStyle?.inputClassName || '', children: radioOptions.map((option, i) => (jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [jsxRuntime.jsx(RadioGroupItem, { value: option, id: `${field.id}-${i}`, "data-testid": `field-radio-${field.id}-${i}` }), jsxRuntime.jsx(Label$2, { htmlFor: `${field.id}-${i}`, className: "text-sm", style: {
|
|
18864
|
+
return (jsxRuntime.jsx(RadioGroup$1, { disabled: isFieldDisabled, className: field.customStyle?.inputClassName || '', children: radioOptions.map((option, i) => (jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [jsxRuntime.jsx(RadioGroupItem, { value: option, id: `${field.id}-${i}`, tabIndex: tabIndexValue, "data-testid": `field-radio-${field.id}-${i}` }), jsxRuntime.jsx(Label$2, { htmlFor: `${field.id}-${i}`, className: "text-sm", style: {
|
|
18754
18865
|
...(field.customStyle?.color ? { color: field.customStyle.color } : {}),
|
|
18755
18866
|
}, children: option })] }, i))) }));
|
|
18756
18867
|
case 'toggle':
|
|
18757
|
-
return (jsxRuntime.jsxs("div", { className: `flex items-center gap-2 ${field.customStyle?.inputClassName || ''}`, children: [jsxRuntime.jsx(Switch, { disabled: isFieldDisabled, "data-testid": `field-toggle-${field.id}` }), jsxRuntime.jsx("span", { className: "text-sm text-foreground", style: {
|
|
18868
|
+
return (jsxRuntime.jsxs("div", { className: `flex items-center gap-2 ${field.customStyle?.inputClassName || ''}`, children: [jsxRuntime.jsx(Switch, { disabled: isFieldDisabled, tabIndex: tabIndexValue, "data-testid": `field-toggle-${field.id}` }), jsxRuntime.jsx("span", { className: "text-sm text-foreground", style: {
|
|
18758
18869
|
...(field.customStyle?.color ? { color: field.customStyle.color } : {}),
|
|
18759
18870
|
}, children: field.props.label })] }));
|
|
18760
18871
|
case 'multiselect':
|
|
@@ -18763,30 +18874,30 @@ function CanvasField({ field, rowId, columnId, isPreviewMode: externalPreviewMod
|
|
|
18763
18874
|
setFieldValue(field.props.key, v);
|
|
18764
18875
|
}, options: field.props.optionsString || [], disabled: isFieldDisabled, maxItems: field.props.multiSelectConfig?.maxItems, className: field.customStyle?.inputClassName }));
|
|
18765
18876
|
case 'date':
|
|
18766
|
-
return (jsxRuntime.jsx(Input, { type: "date", disabled: isFieldDisabled, value: isPreviewMode ? localValue : (field.props.defaultValue || ''), onChange: (e) => isPreviewMode && handleChange(e.target.value), onBlur: handleBlur, tabIndex: tabIndexValue, className: `${inputSize} ${errorClass} ${field.customStyle?.inputClassName || ''}`, style: {
|
|
18877
|
+
return (jsxRuntime.jsx(Input, { type: "date", disabled: isFieldDisabled, autoFocus: isPreviewMode && field.props.autoFocus, value: isPreviewMode ? localValue : (field.props.defaultValue || ''), onChange: (e) => isPreviewMode && handleChange(e.target.value), onBlur: handleBlur, tabIndex: tabIndexValue, className: `${inputSize} ${errorClass} ${field.customStyle?.inputClassName || ''}`, style: {
|
|
18767
18878
|
...(field.customStyle?.color ? { color: field.customStyle.color } : {}),
|
|
18768
18879
|
...(field.customStyle?.backgroundColor ? { backgroundColor: field.customStyle.backgroundColor } : {}),
|
|
18769
|
-
}, "data-testid": `field-date-${field.id}
|
|
18880
|
+
}, "data-testid": `field-date-${field.id}`, "data-field-key": field.props.key }));
|
|
18770
18881
|
case 'time':
|
|
18771
|
-
return (jsxRuntime.jsx(Input, { type: "time", disabled: isFieldDisabled, value: isPreviewMode ? localValue : (field.props.defaultValue || ''), onChange: (e) => isPreviewMode && handleChange(e.target.value), onBlur: handleBlur, tabIndex: tabIndexValue, className: `${inputSize} ${errorClass} ${field.customStyle?.inputClassName || ''}`, style: {
|
|
18882
|
+
return (jsxRuntime.jsx(Input, { type: "time", disabled: isFieldDisabled, autoFocus: isPreviewMode && field.props.autoFocus, value: isPreviewMode ? localValue : (field.props.defaultValue || ''), onChange: (e) => isPreviewMode && handleChange(e.target.value), onBlur: handleBlur, tabIndex: tabIndexValue, className: `${inputSize} ${errorClass} ${field.customStyle?.inputClassName || ''}`, style: {
|
|
18772
18883
|
...(field.customStyle?.color ? { color: field.customStyle.color } : {}),
|
|
18773
18884
|
...(field.customStyle?.backgroundColor ? { backgroundColor: field.customStyle.backgroundColor } : {}),
|
|
18774
|
-
}, "data-testid": `field-time-${field.id}
|
|
18885
|
+
}, "data-testid": `field-time-${field.id}`, "data-field-key": field.props.key }));
|
|
18775
18886
|
case 'daterange':
|
|
18776
|
-
return (jsxRuntime.jsxs("div", { className: `flex gap-2 items-center ${field.customStyle?.inputClassName || ''}`, children: [jsxRuntime.jsx(Input, { type: "date", disabled: isFieldDisabled, className: inputSize, style: {
|
|
18887
|
+
return (jsxRuntime.jsxs("div", { className: `flex gap-2 items-center ${field.customStyle?.inputClassName || ''}`, children: [jsxRuntime.jsx(Input, { type: "date", disabled: isFieldDisabled, tabIndex: tabIndexValue, className: inputSize, style: {
|
|
18777
18888
|
...(field.customStyle?.backgroundColor ? { backgroundColor: field.customStyle.backgroundColor } : {}),
|
|
18778
18889
|
}, "data-testid": `field-daterange-start-${field.id}` }), jsxRuntime.jsx("span", { className: "text-muted-foreground", style: {
|
|
18779
18890
|
...(field.customStyle?.color ? { color: field.customStyle.color } : {}),
|
|
18780
|
-
}, children: "to" }), jsxRuntime.jsx(Input, { type: "date", disabled: isFieldDisabled, className: inputSize, style: {
|
|
18891
|
+
}, children: "to" }), jsxRuntime.jsx(Input, { type: "date", disabled: isFieldDisabled, tabIndex: tabIndexValue !== undefined ? tabIndexValue + 1 : undefined, className: inputSize, style: {
|
|
18781
18892
|
...(field.customStyle?.backgroundColor ? { backgroundColor: field.customStyle.backgroundColor } : {}),
|
|
18782
18893
|
}, "data-testid": `field-daterange-end-${field.id}` })] }));
|
|
18783
18894
|
case 'number':
|
|
18784
|
-
return (jsxRuntime.jsx(Input, { type: "number", placeholder: field.props.placeholder, disabled: isFieldDisabled, value: isPreviewMode ? localValue : (field.props.defaultValue || ''), onChange: (e) => isPreviewMode && handleChange(e.target.value), onBlur: handleBlur, tabIndex: tabIndexValue, className: `${inputSize} ${errorClass} ${field.customStyle?.inputClassName || ''}`, style: {
|
|
18895
|
+
return (jsxRuntime.jsx(Input, { type: "number", placeholder: field.props.placeholder, disabled: isFieldDisabled, autoFocus: isPreviewMode && field.props.autoFocus, value: isPreviewMode ? localValue : (field.props.defaultValue || ''), onChange: (e) => isPreviewMode && handleChange(e.target.value), onBlur: handleBlur, tabIndex: tabIndexValue, className: `${inputSize} ${errorClass} ${field.customStyle?.inputClassName || ''}`, style: {
|
|
18785
18896
|
...(field.customStyle?.color ? { color: field.customStyle.color } : {}),
|
|
18786
18897
|
...(field.customStyle?.backgroundColor ? { backgroundColor: field.customStyle.backgroundColor } : {}),
|
|
18787
|
-
}, "data-testid": `field-number-${field.id}
|
|
18898
|
+
}, "data-testid": `field-number-${field.id}`, "data-field-key": field.props.key }));
|
|
18788
18899
|
case 'email':
|
|
18789
|
-
return (jsxRuntime.jsx(Input, { type: "email", placeholder: field.props.placeholder, disabled: isFieldDisabled, value: isPreviewMode ? localValue : (field.props.defaultValue || ''), onChange: (e) => isPreviewMode && handleChange(e.target.value), onBlur: handleBlur, tabIndex: tabIndexValue, className: `${inputSize} ${errorClass} ${field.customStyle?.inputClassName || ''}`, style: {
|
|
18900
|
+
return (jsxRuntime.jsx(Input, { type: "email", placeholder: field.props.placeholder, disabled: isFieldDisabled, autoFocus: isPreviewMode && field.props.autoFocus, value: isPreviewMode ? localValue : (field.props.defaultValue || ''), onChange: (e) => isPreviewMode && handleChange(e.target.value), onBlur: handleBlur, tabIndex: tabIndexValue, className: `${inputSize} ${errorClass} ${field.customStyle?.inputClassName || ''}`, "data-field-key": field.props.key, style: {
|
|
18790
18901
|
...(field.customStyle?.color ? { color: field.customStyle.color } : {}),
|
|
18791
18902
|
...(field.customStyle?.backgroundColor ? { backgroundColor: field.customStyle.backgroundColor } : {}),
|
|
18792
18903
|
}, "data-testid": `field-email-${field.id}` }));
|
|
@@ -18812,7 +18923,7 @@ function CanvasField({ field, rowId, columnId, isPreviewMode: externalPreviewMod
|
|
|
18812
18923
|
...(field.customStyle?.backgroundColor ? { backgroundColor: field.customStyle.backgroundColor } : {}),
|
|
18813
18924
|
}, "data-testid": `field-richtext-${field.id}` }));
|
|
18814
18925
|
case 'autocomplete':
|
|
18815
|
-
return (jsxRuntime.jsx("div", { className: `relative ${field.customStyle?.inputClassName || ''}`, children: jsxRuntime.jsx(Input, { placeholder: field.props.placeholder || 'Start typing...', disabled: isFieldDisabled, value: isPreviewMode ? localValue : '', onChange: (e) => isPreviewMode && handleChange(e.target.value), className: `${inputSize} ${errorClass}`, style: {
|
|
18926
|
+
return (jsxRuntime.jsx("div", { className: `relative ${field.customStyle?.inputClassName || ''}`, children: jsxRuntime.jsx(Input, { placeholder: field.props.placeholder || 'Start typing...', disabled: isFieldDisabled, value: isPreviewMode ? localValue : '', onChange: (e) => isPreviewMode && handleChange(e.target.value), tabIndex: tabIndexValue, className: `${inputSize} ${errorClass}`, style: {
|
|
18816
18927
|
...(field.customStyle?.color ? { color: field.customStyle.color } : {}),
|
|
18817
18928
|
...(field.customStyle?.backgroundColor ? { backgroundColor: field.customStyle.backgroundColor } : {}),
|
|
18818
18929
|
}, "data-testid": `field-autocomplete-${field.id}` }) }));
|
|
@@ -18820,7 +18931,7 @@ function CanvasField({ field, rowId, columnId, isPreviewMode: externalPreviewMod
|
|
|
18820
18931
|
return (jsxRuntime.jsxs("div", { className: `space-y-2 ${field.customStyle?.inputClassName || ''}`, children: [jsxRuntime.jsx(Slider, { value: sliderValue, onValueChange: (v) => {
|
|
18821
18932
|
setSliderValue(v);
|
|
18822
18933
|
setFieldValue(field.props.key, v[0]);
|
|
18823
|
-
}, min: field.validation?.min || 0, max: field.validation?.max || 100, step: 1, disabled: isFieldDisabled, "data-testid": `field-slider-${field.id}` }), jsxRuntime.jsxs("div", { className: "flex justify-between text-xs text-muted-foreground", children: [jsxRuntime.jsx("span", { children: field.validation?.min || 0 }), jsxRuntime.jsx("span", { className: "font-medium text-foreground", style: {
|
|
18934
|
+
}, min: field.validation?.min || 0, max: field.validation?.max || 100, step: 1, disabled: isFieldDisabled, tabIndex: tabIndexValue, "data-testid": `field-slider-${field.id}` }), jsxRuntime.jsxs("div", { className: "flex justify-between text-xs text-muted-foreground", children: [jsxRuntime.jsx("span", { children: field.validation?.min || 0 }), jsxRuntime.jsx("span", { className: "font-medium text-foreground", style: {
|
|
18824
18935
|
...(field.customStyle?.color ? { color: field.customStyle.color } : {}),
|
|
18825
18936
|
}, children: sliderValue[0] }), jsxRuntime.jsx("span", { children: field.validation?.max || 100 })] })] }));
|
|
18826
18937
|
case 'header':
|
|
@@ -19815,15 +19926,30 @@ function FieldProperties() {
|
|
|
19815
19926
|
});
|
|
19816
19927
|
}, className: "w-full gap-2", children: [jsxRuntime.jsx(Plus, { className: "h-4 w-4" }), "Add Attribute"] })] })] }), jsxRuntime.jsx(Separator$1, {}), hasOptions && (jsxRuntime.jsxs("div", { className: "space-y-2", children: [jsxRuntime.jsx(Label$2, { className: "text-sm", children: "Options" }), jsxRuntime.jsxs("div", { className: "space-y-2", children: [getOptionsArray().map((option, i) => (jsxRuntime.jsxs("div", { className: "flex gap-2", children: [jsxRuntime.jsx(Input, { value: option, onChange: (e) => handleUpdateOption(i, e.target.value), className: "flex-1", "data-testid": `input-option-${i}` }), jsxRuntime.jsx(Button, { variant: "outline", size: "icon", onClick: () => handleRemoveOption(i), "data-testid": `button-remove-option-${i}`, children: jsxRuntime.jsx(Trash2, { className: "h-4 w-4" }) })] }, i))), jsxRuntime.jsxs(Button, { variant: "outline", size: "sm", onClick: handleAddOption, className: "w-full gap-2", "data-testid": "button-add-option", children: [jsxRuntime.jsx(Plus, { className: "h-4 w-4" }), "Add Option"] })] })] })), field.type === 'button' && (jsxRuntime.jsxs("div", { className: "space-y-4", children: [jsxRuntime.jsx(Separator$1, {}), jsxRuntime.jsx("h4", { className: "text-xs font-semibold uppercase tracking-wide text-muted-foreground", children: "Button Settings" }), jsxRuntime.jsxs("div", { className: "space-y-2", children: [jsxRuntime.jsx(Label$2, { className: "text-sm", children: "Action" }), jsxRuntime.jsxs(Select, { value: field.props.buttonConfig?.action || 'submit', onValueChange: (value) => handleUpdateProp('buttonConfig', { ...field.props.buttonConfig, action: value }), children: [jsxRuntime.jsx(SelectTrigger, { children: jsxRuntime.jsx(SelectValue, {}) }), jsxRuntime.jsxs(SelectContent, { children: [jsxRuntime.jsx(SelectItem, { value: "submit", children: "Submit Form" }), jsxRuntime.jsx(SelectItem, { value: "reset", children: "Reset Form" }), jsxRuntime.jsx(SelectItem, { value: "custom", children: "Custom Action" })] })] })] }), jsxRuntime.jsxs("div", { className: "space-y-2", children: [jsxRuntime.jsx(Label$2, { className: "text-sm", children: "Variant" }), jsxRuntime.jsxs(Select, { value: field.props.buttonConfig?.variant || 'default', onValueChange: (value) => handleUpdateProp('buttonConfig', { ...field.props.buttonConfig, variant: value }), children: [jsxRuntime.jsx(SelectTrigger, { children: jsxRuntime.jsx(SelectValue, {}) }), jsxRuntime.jsxs(SelectContent, { children: [jsxRuntime.jsx(SelectItem, { value: "default", children: "Default" }), jsxRuntime.jsx(SelectItem, { value: "outline", children: "Outline" }), jsxRuntime.jsx(SelectItem, { value: "secondary", children: "Secondary" }), jsxRuntime.jsx(SelectItem, { value: "destructive", children: "Destructive" }), jsxRuntime.jsx(SelectItem, { value: "ghost", children: "Ghost" })] })] })] })] })), field.type === 'pattern' && (jsxRuntime.jsxs("div", { className: "space-y-4", children: [jsxRuntime.jsx(Separator$1, {}), jsxRuntime.jsx("h4", { className: "text-xs font-semibold uppercase tracking-wide text-muted-foreground", children: "Pattern Format" }), jsxRuntime.jsxs("div", { className: "space-y-2", children: [jsxRuntime.jsx(Label$2, { className: "text-sm", children: "Format Pattern" }), jsxRuntime.jsx(Input, { value: field.props.patternConfig?.format || '(###) ###-####', onChange: (e) => handleUpdateProp('patternConfig', { ...field.props.patternConfig, format: e.target.value }), placeholder: "(###) ###-####" }), jsxRuntime.jsx("p", { className: "text-xs text-muted-foreground", children: "Use # for digit placeholders" })] }), jsxRuntime.jsxs("div", { className: "space-y-2", children: [jsxRuntime.jsx(Label$2, { className: "text-sm", children: "Mask Character" }), jsxRuntime.jsx(Input, { value: field.props.patternConfig?.mask || '_', onChange: (e) => handleUpdateProp('patternConfig', { ...field.props.patternConfig, mask: e.target.value }), maxLength: 1 })] })] })), field.type === 'qrcode' && (jsxRuntime.jsxs("div", { className: "space-y-4", children: [jsxRuntime.jsx(Separator$1, {}), jsxRuntime.jsx("h4", { className: "text-xs font-semibold uppercase tracking-wide text-muted-foreground", children: "QR Code Settings" }), jsxRuntime.jsxs("div", { className: "space-y-2", children: [jsxRuntime.jsx(Label$2, { className: "text-sm", children: "QR Value" }), jsxRuntime.jsx(Input, { value: field.props.qrCodeConfig?.value || 'https://example.com', onChange: (e) => handleUpdateProp('qrCodeConfig', { ...field.props.qrCodeConfig, value: e.target.value }), placeholder: "https://example.com" })] }), jsxRuntime.jsxs("div", { className: "space-y-2", children: [jsxRuntime.jsx(Label$2, { className: "text-sm", children: "Size (px)" }), jsxRuntime.jsx(Input, { type: "number", value: field.props.qrCodeConfig?.size || 128, onChange: (e) => handleUpdateProp('qrCodeConfig', { ...field.props.qrCodeConfig, size: parseInt(e.target.value) }), min: 64, max: 512 })] })] })), field.type === 'container' && (jsxRuntime.jsxs("div", { className: "space-y-4", children: [jsxRuntime.jsx(Separator$1, {}), jsxRuntime.jsx("h4", { className: "text-xs font-semibold uppercase tracking-wide text-muted-foreground", children: "Container Settings" }), jsxRuntime.jsxs("div", { className: "space-y-2", children: [jsxRuntime.jsx(Label$2, { className: "text-sm", children: "Direction" }), jsxRuntime.jsxs(Select, { value: field.props.containerConfig?.direction || 'row', onValueChange: (value) => handleUpdateProp('containerConfig', { ...field.props.containerConfig, direction: value }), children: [jsxRuntime.jsx(SelectTrigger, { "data-testid": "select-container-direction", children: jsxRuntime.jsx(SelectValue, {}) }), jsxRuntime.jsxs(SelectContent, { children: [jsxRuntime.jsx(SelectItem, { value: "row", children: "Row (Horizontal)" }), jsxRuntime.jsx(SelectItem, { value: "column", children: "Column (Vertical)" })] })] })] }), jsxRuntime.jsxs("div", { className: "space-y-2", children: [jsxRuntime.jsx(Label$2, { className: "text-sm", children: "Inner Field Size (Density)" }), jsxRuntime.jsxs(Select, { value: field.props.containerConfig?.fieldSize || 'normal', onValueChange: (value) => handleUpdateProp('containerConfig', { ...field.props.containerConfig, fieldSize: value }), children: [jsxRuntime.jsx(SelectTrigger, { "data-testid": "container-field-size", children: jsxRuntime.jsx(SelectValue, {}) }), jsxRuntime.jsxs(SelectContent, { children: [jsxRuntime.jsx(SelectItem, { value: "compact", "data-testid": "field-size-compact", children: "Compact (Minimal)" }), jsxRuntime.jsx(SelectItem, { value: "normal", "data-testid": "field-size-normal", children: "Normal" }), jsxRuntime.jsx(SelectItem, { value: "comfortable", "data-testid": "field-size-comfortable", children: "Comfortable (Spacious)" })] })] }), jsxRuntime.jsx("p", { className: "text-xs text-muted-foreground", children: "Controls padding and font sizes for fields inside this container" })] }), jsxRuntime.jsx(Separator$1, {}), jsxRuntime.jsx("h5", { className: "text-xs font-medium text-muted-foreground", children: "Spacing & Layout" }), jsxRuntime.jsxs("div", { className: "space-y-2", children: [jsxRuntime.jsx(Label$2, { className: "text-sm", children: "Gap (between items)" }), jsxRuntime.jsx(Input, { type: "number", value: field.props.containerConfig?.gap ?? 4, onChange: (e) => handleUpdateProp('containerConfig', { ...field.props.containerConfig, gap: parseInt(e.target.value) }), min: 0, max: 16 }), jsxRuntime.jsx("p", { className: "text-xs text-muted-foreground", children: "Space between child elements (0-16)" })] }), jsxRuntime.jsxs("div", { className: "space-y-2", children: [jsxRuntime.jsx(Label$2, { className: "text-sm", children: "Padding (inner space)" }), jsxRuntime.jsx(Input, { type: "number", value: field.props.containerConfig?.padding ?? 4, onChange: (e) => handleUpdateProp('containerConfig', { ...field.props.containerConfig, padding: parseInt(e.target.value) }), min: 0, max: 16 }), jsxRuntime.jsx("p", { className: "text-xs text-muted-foreground", children: "Inner spacing around content (0-16)" })] }), jsxRuntime.jsx(Separator$1, {}), jsxRuntime.jsx("h5", { className: "text-xs font-medium text-muted-foreground", children: "Flex Properties" }), jsxRuntime.jsxs("div", { className: "space-y-2", children: [jsxRuntime.jsx(Label$2, { className: "text-sm", children: "Justify Content" }), jsxRuntime.jsxs(Select, { value: field.props.containerConfig?.justifyContent || 'flex-start', onValueChange: (value) => handleUpdateProp('containerConfig', { ...field.props.containerConfig, justifyContent: value }), children: [jsxRuntime.jsx(SelectTrigger, { "data-testid": "select-justify-content", children: jsxRuntime.jsx(SelectValue, {}) }), jsxRuntime.jsxs(SelectContent, { children: [jsxRuntime.jsx(SelectItem, { value: "flex-start", children: "Start" }), jsxRuntime.jsx(SelectItem, { value: "flex-end", children: "End" }), jsxRuntime.jsx(SelectItem, { value: "center", children: "Center" }), jsxRuntime.jsx(SelectItem, { value: "space-between", children: "Space Between" }), jsxRuntime.jsx(SelectItem, { value: "space-around", children: "Space Around" }), jsxRuntime.jsx(SelectItem, { value: "space-evenly", children: "Space Evenly" })] })] })] }), jsxRuntime.jsxs("div", { className: "space-y-2", children: [jsxRuntime.jsx(Label$2, { className: "text-sm", children: "Align Items" }), jsxRuntime.jsxs(Select, { value: field.props.containerConfig?.alignItems || 'stretch', onValueChange: (value) => handleUpdateProp('containerConfig', { ...field.props.containerConfig, alignItems: value }), children: [jsxRuntime.jsx(SelectTrigger, { "data-testid": "select-align-items", children: jsxRuntime.jsx(SelectValue, {}) }), jsxRuntime.jsxs(SelectContent, { children: [jsxRuntime.jsx(SelectItem, { value: "flex-start", children: "Start" }), jsxRuntime.jsx(SelectItem, { value: "flex-end", children: "End" }), jsxRuntime.jsx(SelectItem, { value: "center", children: "Center" }), jsxRuntime.jsx(SelectItem, { value: "stretch", children: "Stretch" }), jsxRuntime.jsx(SelectItem, { value: "baseline", children: "Baseline" })] })] })] }), jsxRuntime.jsxs("div", { className: "space-y-2", children: [jsxRuntime.jsx(Label$2, { className: "text-sm", children: "Flex Wrap" }), jsxRuntime.jsxs(Select, { value: field.props.containerConfig?.flexWrap || 'wrap', onValueChange: (value) => handleUpdateProp('containerConfig', { ...field.props.containerConfig, flexWrap: value }), children: [jsxRuntime.jsx(SelectTrigger, { "data-testid": "select-flex-wrap", children: jsxRuntime.jsx(SelectValue, {}) }), jsxRuntime.jsxs(SelectContent, { children: [jsxRuntime.jsx(SelectItem, { value: "wrap", children: "Wrap" }), jsxRuntime.jsx(SelectItem, { value: "nowrap", children: "No Wrap" })] })] })] }), jsxRuntime.jsxs("div", { className: "flex items-center justify-between", children: [jsxRuntime.jsx(Label$2, { className: "text-sm", children: "Show Border" }), jsxRuntime.jsx(Switch, { checked: field.props.containerConfig?.border || false, onCheckedChange: (checked) => handleUpdateProp('containerConfig', { ...field.props.containerConfig, border: checked }) })] }), jsxRuntime.jsx(Separator$1, {}), jsxRuntime.jsxs("div", { className: "space-y-3", children: [jsxRuntime.jsxs("div", { className: "flex items-center justify-between", children: [jsxRuntime.jsx("h5", { className: "text-sm font-medium", children: "Container Fields" }), jsxRuntime.jsxs("span", { className: "text-xs text-muted-foreground", children: [(field.props.containerConfig?.fields || []).length, " field(s)"] })] }), jsxRuntime.jsx("p", { className: "text-xs text-muted-foreground", children: "Drag fields onto the container. Set each field's width in its properties." })] })] })), field.type === 'table' && (jsxRuntime.jsxs("div", { className: "space-y-4 p-3 bg-muted/30 rounded-md", children: [jsxRuntime.jsx("h4", { className: "text-sm font-medium", children: "Table Configuration" }), jsxRuntime.jsxs("div", { className: "space-y-3", children: [jsxRuntime.jsxs("div", { className: "flex items-center justify-between", children: [jsxRuntime.jsx(Label$2, { className: "text-sm", children: "Show Row Numbers" }), jsxRuntime.jsx(Switch, { checked: field.props.tableConfig?.showRowNumbers ?? true, onCheckedChange: (checked) => handleUpdateProp('tableConfig', { ...field.props.tableConfig, showRowNumbers: checked }) })] }), jsxRuntime.jsxs("div", { className: "flex items-center justify-between", children: [jsxRuntime.jsx(Label$2, { className: "text-sm", children: "Allow Add Rows" }), jsxRuntime.jsx(Switch, { checked: field.props.tableConfig?.allowAddRows ?? true, onCheckedChange: (checked) => handleUpdateProp('tableConfig', { ...field.props.tableConfig, allowAddRows: checked }) })] }), jsxRuntime.jsxs("div", { className: "flex items-center justify-between", children: [jsxRuntime.jsx(Label$2, { className: "text-sm", children: "Allow Delete Rows" }), jsxRuntime.jsx(Switch, { checked: field.props.tableConfig?.allowDeleteRows ?? false, onCheckedChange: (checked) => handleUpdateProp('tableConfig', { ...field.props.tableConfig, allowDeleteRows: checked }) })] }), jsxRuntime.jsxs("div", { className: "flex items-center justify-between", children: [jsxRuntime.jsx(Label$2, { className: "text-sm", children: "Striped Rows" }), jsxRuntime.jsx(Switch, { checked: field.props.tableConfig?.striped ?? false, onCheckedChange: (checked) => handleUpdateProp('tableConfig', { ...field.props.tableConfig, striped: checked }) })] }), jsxRuntime.jsxs("div", { className: "flex items-center justify-between", children: [jsxRuntime.jsx(Label$2, { className: "text-sm", children: "Bordered" }), jsxRuntime.jsx(Switch, { checked: field.props.tableConfig?.bordered ?? true, onCheckedChange: (checked) => handleUpdateProp('tableConfig', { ...field.props.tableConfig, bordered: checked }) })] }), jsxRuntime.jsxs("div", { className: "flex items-center justify-between", children: [jsxRuntime.jsx(Label$2, { className: "text-sm", children: "Compact" }), jsxRuntime.jsx(Switch, { checked: field.props.tableConfig?.compact ?? false, onCheckedChange: (checked) => handleUpdateProp('tableConfig', { ...field.props.tableConfig, compact: checked }) })] })] }), jsxRuntime.jsx(Separator$1, {}), jsxRuntime.jsxs("div", { className: "grid grid-cols-2 gap-3", children: [jsxRuntime.jsxs("div", { className: "space-y-2", children: [jsxRuntime.jsx(Label$2, { className: "text-sm", children: "Min Rows" }), jsxRuntime.jsx(Input, { type: "number", value: field.props.tableConfig?.minRows ?? 1, onChange: (e) => handleUpdateProp('tableConfig', { ...field.props.tableConfig, minRows: parseInt(e.target.value) || 1 }), min: 1, max: 100 })] }), jsxRuntime.jsxs("div", { className: "space-y-2", children: [jsxRuntime.jsx(Label$2, { className: "text-sm", children: "Max Rows" }), jsxRuntime.jsx(Input, { type: "number", value: field.props.tableConfig?.maxRows ?? 100, onChange: (e) => handleUpdateProp('tableConfig', { ...field.props.tableConfig, maxRows: parseInt(e.target.value) || 100 }), min: 1, max: 1000 })] })] }), jsxRuntime.jsx(Separator$1, {}), jsxRuntime.jsxs("div", { className: "space-y-3", children: [jsxRuntime.jsxs("div", { className: "flex items-center justify-between", children: [jsxRuntime.jsx("h5", { className: "text-sm font-medium", children: "Columns" }), jsxRuntime.jsxs(Button, { variant: "outline", size: "sm", onClick: () => {
|
|
19817
19928
|
const currentColumns = field.props.tableConfig?.columns || [];
|
|
19929
|
+
const totalColumns = currentColumns.length + 1;
|
|
19930
|
+
const widthPerColumn = Math.floor(100 / totalColumns);
|
|
19931
|
+
const extraWidth = 100 % totalColumns;
|
|
19932
|
+
const updatedColumns = currentColumns.map((c, idx) => ({
|
|
19933
|
+
...c,
|
|
19934
|
+
width: `${widthPerColumn + (idx < extraWidth ? 1 : 0)}%`
|
|
19935
|
+
}));
|
|
19818
19936
|
const newColumn = {
|
|
19819
19937
|
key: `col_${Date.now()}`,
|
|
19820
|
-
label: `Column ${
|
|
19938
|
+
label: `Column ${totalColumns}`,
|
|
19821
19939
|
type: 'text',
|
|
19940
|
+
width: `${widthPerColumn}%`,
|
|
19822
19941
|
};
|
|
19823
|
-
handleUpdateProp('tableConfig', { ...field.props.tableConfig, columns: [...
|
|
19942
|
+
handleUpdateProp('tableConfig', { ...field.props.tableConfig, columns: [...updatedColumns, newColumn] });
|
|
19824
19943
|
}, children: [jsxRuntime.jsx(Plus, { className: "h-4 w-4 mr-1" }), "Add Column"] })] }), (field.props.tableConfig?.columns || []).map((col, colIndex) => (jsxRuntime.jsxs("div", { className: "p-3 bg-background rounded-md border border-border space-y-3", children: [jsxRuntime.jsxs("div", { className: "flex items-center justify-between", children: [jsxRuntime.jsxs("span", { className: "text-xs font-medium text-muted-foreground", children: ["Column ", colIndex + 1] }), jsxRuntime.jsx(Button, { variant: "ghost", size: "icon", className: "h-6 w-6", onClick: () => {
|
|
19825
19944
|
const currentColumns = [...(field.props.tableConfig?.columns || [])];
|
|
19826
19945
|
currentColumns.splice(colIndex, 1);
|
|
19946
|
+
if (currentColumns.length > 0) {
|
|
19947
|
+
const widthPerColumn = Math.floor(100 / currentColumns.length);
|
|
19948
|
+
const extraWidth = 100 % currentColumns.length;
|
|
19949
|
+
currentColumns.forEach((c, idx) => {
|
|
19950
|
+
currentColumns[idx] = { ...c, width: `${widthPerColumn + (idx < extraWidth ? 1 : 0)}%` };
|
|
19951
|
+
});
|
|
19952
|
+
}
|
|
19827
19953
|
handleUpdateProp('tableConfig', { ...field.props.tableConfig, columns: currentColumns });
|
|
19828
19954
|
}, children: jsxRuntime.jsx(Trash2, { className: "h-3 w-3 text-destructive" }) })] }), jsxRuntime.jsxs("div", { className: "grid grid-cols-2 gap-2", children: [jsxRuntime.jsxs("div", { className: "space-y-1", children: [jsxRuntime.jsx(Label$2, { className: "text-xs", children: "Key" }), jsxRuntime.jsx(Input, { value: col.key, onChange: (e) => {
|
|
19829
19955
|
const currentColumns = [...(field.props.tableConfig?.columns || [])];
|
|
@@ -19837,11 +19963,12 @@ function FieldProperties() {
|
|
|
19837
19963
|
const currentColumns = [...(field.props.tableConfig?.columns || [])];
|
|
19838
19964
|
currentColumns[colIndex] = { ...col, type: value };
|
|
19839
19965
|
handleUpdateProp('tableConfig', { ...field.props.tableConfig, columns: currentColumns });
|
|
19840
|
-
}, children: [jsxRuntime.jsx(SelectTrigger, { className: "h-8 text-xs", children: jsxRuntime.jsx(SelectValue, {}) }), jsxRuntime.jsxs(SelectContent, { children: [jsxRuntime.jsx(SelectItem, { value: "text", children: "Text" }), jsxRuntime.jsx(SelectItem, { value: "number", children: "Number" }), jsxRuntime.jsx(SelectItem, { value: "email", children: "Email" }), jsxRuntime.jsx(SelectItem, { value: "date", children: "Date" }), jsxRuntime.jsx(SelectItem, { value: "select", children: "Select" }), jsxRuntime.jsx(SelectItem, { value: "checkbox", children: "Checkbox" })] })] })] }), jsxRuntime.jsxs("div", { className: "space-y-1", children: [jsxRuntime.jsx(Label$2, { className: "text-xs", children: "Width" }), jsxRuntime.jsx(Input, { value: col.width || '', onChange: (e) => {
|
|
19966
|
+
}, children: [jsxRuntime.jsx(SelectTrigger, { className: "h-8 text-xs", children: jsxRuntime.jsx(SelectValue, {}) }), jsxRuntime.jsxs(SelectContent, { children: [jsxRuntime.jsx(SelectItem, { value: "text", children: "Text" }), jsxRuntime.jsx(SelectItem, { value: "number", children: "Number" }), jsxRuntime.jsx(SelectItem, { value: "email", children: "Email" }), jsxRuntime.jsx(SelectItem, { value: "date", children: "Date" }), jsxRuntime.jsx(SelectItem, { value: "select", children: "Select" }), jsxRuntime.jsx(SelectItem, { value: "checkbox", children: "Checkbox" })] })] })] }), jsxRuntime.jsxs("div", { className: "space-y-1", children: [jsxRuntime.jsx(Label$2, { className: "text-xs", children: "%Width" }), jsxRuntime.jsx(Input, { type: "number", value: col.width ? parseInt(col.width) || '' : '', onChange: (e) => {
|
|
19841
19967
|
const currentColumns = [...(field.props.tableConfig?.columns || [])];
|
|
19842
|
-
|
|
19968
|
+
const newWidth = parseInt(e.target.value) || 0;
|
|
19969
|
+
currentColumns[colIndex] = { ...col, width: newWidth > 0 ? `${newWidth}%` : '' };
|
|
19843
19970
|
handleUpdateProp('tableConfig', { ...field.props.tableConfig, columns: currentColumns });
|
|
19844
|
-
}, placeholder: "
|
|
19971
|
+
}, placeholder: "25", min: 1, max: 100, className: "text-xs h-8" })] }), jsxRuntime.jsxs("div", { className: "space-y-1", children: [jsxRuntime.jsx(Label$2, { className: "text-xs", children: "Required" }), jsxRuntime.jsx("div", { className: "flex items-center h-8", children: jsxRuntime.jsx(Switch, { checked: col.required || false, onCheckedChange: (checked) => {
|
|
19845
19972
|
const currentColumns = [...(field.props.tableConfig?.columns || [])];
|
|
19846
19973
|
currentColumns[colIndex] = { ...col, required: checked };
|
|
19847
19974
|
handleUpdateProp('tableConfig', { ...field.props.tableConfig, columns: currentColumns });
|
|
@@ -19869,7 +19996,12 @@ function FieldProperties() {
|
|
|
19869
19996
|
currentOptions.splice(optIndex, 1);
|
|
19870
19997
|
currentColumns[colIndex] = { ...col, options: currentOptions };
|
|
19871
19998
|
handleUpdateProp('tableConfig', { ...field.props.tableConfig, columns: currentColumns });
|
|
19872
|
-
}, children: jsxRuntime.jsx(Trash2, { className: "h-3 w-3 text-destructive" }) })] }, optIndex))), (!col.options || col.options.length === 0) && (jsxRuntime.jsx("p", { className: "text-xs text-muted-foreground italic", children: "Hen\u00FCz se\u00E7enek eklenmedi" }))] }))] }, col
|
|
19999
|
+
}, children: jsxRuntime.jsx(Trash2, { className: "h-3 w-3 text-destructive" }) })] }, optIndex))), (!col.options || col.options.length === 0) && (jsxRuntime.jsx("p", { className: "text-xs text-muted-foreground italic", children: "Hen\u00FCz se\u00E7enek eklenmedi" }))] }))] }, `col-${colIndex}`))), (field.props.tableConfig?.columns || []).length > 0 && (() => {
|
|
20000
|
+
const columns = field.props.tableConfig?.columns || [];
|
|
20001
|
+
const totalWidth = columns.reduce((sum, c) => sum + (parseInt(c.width || '0') || 0), 0);
|
|
20002
|
+
const isValid = totalWidth === 100;
|
|
20003
|
+
return (jsxRuntime.jsxs("div", { className: `flex items-center justify-between p-2 rounded-md text-xs ${isValid ? 'bg-green-500/10 text-green-600 dark:text-green-400' : 'bg-destructive/10 text-destructive'}`, children: [jsxRuntime.jsxs("span", { className: "font-medium", children: ["Total Width: ", totalWidth, "%"] }), !isValid && (jsxRuntime.jsx("span", { children: "Must equal 100%" })), isValid && (jsxRuntime.jsx("span", { children: "\u2713" }))] }));
|
|
20004
|
+
})()] })] })), (() => {
|
|
19873
20005
|
const staticDisplayTypes = ['spacer', 'divider', 'header', 'subheader', 'label', 'paragraph', 'alert', 'image', 'qrcode', 'button'];
|
|
19874
20006
|
if (staticDisplayTypes.includes(field.type))
|
|
19875
20007
|
return null;
|
|
@@ -19880,7 +20012,7 @@ function FieldProperties() {
|
|
|
19880
20012
|
return (jsxRuntime.jsx("div", { className: "text-center py-8 text-muted-foreground", children: jsxRuntime.jsx("p", { className: "text-sm", children: "Bu bile\u015Fen i\u00E7in do\u011Frulama kurallar\u0131 gerekli de\u011Fil." }) }));
|
|
19881
20013
|
}
|
|
19882
20014
|
return (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsxs("div", { className: "flex items-center gap-2 mb-4", children: [jsxRuntime.jsx(Settings2, { className: "h-4 w-4 text-muted-foreground" }), jsxRuntime.jsx("span", { className: "text-sm font-medium", children: "Validation Rules" })] }), jsxRuntime.jsxs("div", { className: "space-y-3 pb-4", children: [jsxRuntime.jsxs("div", { className: "flex items-center justify-between", children: [jsxRuntime.jsx(Label$2, { className: "text-sm", children: "Auto Validate" }), jsxRuntime.jsx(Switch, { checked: field.validation?.autoValidate || false, onCheckedChange: (checked) => handleUpdateValidation('autoValidate', checked) })] }), jsxRuntime.jsx("p", { className: "text-xs text-muted-foreground", children: "Validate while typing" }), jsxRuntime.jsxs("div", { className: "flex items-center justify-between", children: [jsxRuntime.jsx(Label$2, { className: "text-sm", children: "Validate on Blur" }), jsxRuntime.jsx(Switch, { checked: field.validation?.validateOnBlur ?? true, onCheckedChange: (checked) => handleUpdateValidation('validateOnBlur', checked) })] }), jsxRuntime.jsxs("div", { className: "flex items-center justify-between", children: [jsxRuntime.jsx(Label$2, { className: "text-sm", children: "Validate on Change" }), jsxRuntime.jsx(Switch, { checked: field.validation?.validateOnChange || false, onCheckedChange: (checked) => handleUpdateValidation('validateOnChange', checked) })] })] }), jsxRuntime.jsx(Separator$1, {}), jsxRuntime.jsxs("div", { className: "space-y-2 pt-4", children: [jsxRuntime.jsx(Label$2, { className: "text-sm", children: "Validation Type" }), jsxRuntime.jsxs(Select, { value: field.validation?.validationType || '', onValueChange: (value) => handleUpdateValidation('validationType', value || undefined), children: [jsxRuntime.jsx(SelectTrigger, { children: jsxRuntime.jsx(SelectValue, { placeholder: "None" }) }), jsxRuntime.jsxs(SelectContent, { children: [jsxRuntime.jsx(SelectItem, { value: "email", children: "Email" }), jsxRuntime.jsx(SelectItem, { value: "url", children: "URL" }), jsxRuntime.jsx(SelectItem, { value: "phone", children: "Phone" }), jsxRuntime.jsx(SelectItem, { value: "custom", children: "Custom" })] })] })] }), jsxRuntime.jsxs("div", { className: "space-y-2", children: [jsxRuntime.jsx(Label$2, { className: "text-sm", children: "Min Length" }), jsxRuntime.jsx(Input, { type: "number", min: 0, value: field.validation?.minLength || '', onChange: (e) => handleUpdateValidation('minLength', e.target.value ? parseInt(e.target.value) : undefined), "data-testid": "input-min-length" })] }), jsxRuntime.jsxs("div", { className: "space-y-2", children: [jsxRuntime.jsx(Label$2, { className: "text-sm", children: "Max Length" }), jsxRuntime.jsx(Input, { type: "number", min: 0, value: field.validation?.maxLength || '', onChange: (e) => handleUpdateValidation('maxLength', e.target.value ? parseInt(e.target.value) : undefined), "data-testid": "input-max-length" })] }), ['number', 'slider'].includes(field.type) && (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsxs("div", { className: "space-y-2", children: [jsxRuntime.jsx(Label$2, { className: "text-sm", children: "Min Value" }), jsxRuntime.jsx(Input, { type: "number", value: field.validation?.min ?? '', onChange: (e) => handleUpdateValidation('min', e.target.value ? parseFloat(e.target.value) : undefined), "data-testid": "input-min-value" })] }), jsxRuntime.jsxs("div", { className: "space-y-2", children: [jsxRuntime.jsx(Label$2, { className: "text-sm", children: "Max Value" }), jsxRuntime.jsx(Input, { type: "number", value: field.validation?.max ?? '', onChange: (e) => handleUpdateValidation('max', e.target.value ? parseFloat(e.target.value) : undefined), "data-testid": "input-max-value" })] })] })), jsxRuntime.jsxs("div", { className: "space-y-2", children: [jsxRuntime.jsx(Label$2, { className: "text-sm", children: "Pattern (Regex)" }), jsxRuntime.jsx(Input, { value: field.validation?.pattern || '', onChange: (e) => handleUpdateValidation('pattern', e.target.value || undefined), placeholder: "^[a-zA-Z]+$", className: "font-mono text-sm", "data-testid": "input-pattern" })] }), jsxRuntime.jsxs("div", { className: "space-y-2", children: [jsxRuntime.jsx(Label$2, { className: "text-sm", children: "Custom Error Message" }), jsxRuntime.jsx(Input, { value: field.validation?.errorMessage || '', onChange: (e) => handleUpdateValidation('errorMessage', e.target.value || undefined), placeholder: "Please enter a valid value", "data-testid": "input-error-message" })] }), jsxRuntime.jsxs("div", { className: "space-y-2", children: [jsxRuntime.jsx(Label$2, { className: "text-sm", children: "Custom Validation (JS)" }), jsxRuntime.jsx(Textarea, { value: field.validation?.customValidation || '', onChange: (e) => handleUpdateValidation('customValidation', e.target.value || undefined), placeholder: "return value.length > 5;", className: "font-mono text-sm min-h-[80px]" }), jsxRuntime.jsx("p", { className: "text-xs text-muted-foreground", children: "Write JavaScript that returns true for valid values" })] }), jsxRuntime.jsx(Separator$1, {}), jsxRuntime.jsxs("div", { className: "flex items-center justify-between", children: [jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [jsxRuntime.jsx(Zap, { className: "h-4 w-4 text-muted-foreground" }), jsxRuntime.jsx(Label$2, { className: "text-sm font-medium", children: "Conditional Logic" })] }), jsxRuntime.jsx(Switch, { checked: field.conditionalLogic?.enabled || false, onCheckedChange: (checked) => handleUpdateConditionalLogic({ enabled: checked }) })] }), field.conditionalLogic?.enabled && (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsxs("div", { className: "space-y-2", children: [jsxRuntime.jsx(Label$2, { className: "text-sm", children: "Action" }), jsxRuntime.jsxs(Select, { value: field.conditionalLogic?.action || 'show', onValueChange: (value) => handleUpdateConditionalLogic({ action: value }), children: [jsxRuntime.jsx(SelectTrigger, { children: jsxRuntime.jsx(SelectValue, {}) }), jsxRuntime.jsxs(SelectContent, { children: [jsxRuntime.jsx(SelectItem, { value: "show", children: "Show this field" }), jsxRuntime.jsx(SelectItem, { value: "hide", children: "Hide this field" }), jsxRuntime.jsx(SelectItem, { value: "enable", children: "Enable this field" }), jsxRuntime.jsx(SelectItem, { value: "disable", children: "Disable this field" }), jsxRuntime.jsx(SelectItem, { value: "require", children: "Make required" })] })] })] }), jsxRuntime.jsxs("div", { className: "space-y-2", children: [jsxRuntime.jsx(Label$2, { className: "text-sm", children: "When" }), jsxRuntime.jsxs(Select, { value: field.conditionalLogic?.logicType || 'all', onValueChange: (value) => handleUpdateConditionalLogic({ logicType: value }), children: [jsxRuntime.jsx(SelectTrigger, { children: jsxRuntime.jsx(SelectValue, {}) }), jsxRuntime.jsxs(SelectContent, { children: [jsxRuntime.jsx(SelectItem, { value: "all", children: "All conditions are met" }), jsxRuntime.jsx(SelectItem, { value: "any", children: "Any condition is met" })] })] })] }), jsxRuntime.jsx(Separator$1, {}), jsxRuntime.jsxs("div", { className: "space-y-3", children: [jsxRuntime.jsx(Label$2, { className: "text-sm font-medium", children: "Conditions" }), (field.conditionalLogic?.conditions || []).map((condition, index) => (jsxRuntime.jsxs("div", { className: "p-3 border border-border rounded-md space-y-3", children: [jsxRuntime.jsxs("div", { className: "flex items-center justify-between", children: [jsxRuntime.jsxs(Badge, { variant: "secondary", children: ["Condition ", index + 1] }), jsxRuntime.jsx(Button, { variant: "ghost", size: "icon", onClick: () => removeCondition(index), children: jsxRuntime.jsx(Trash2, { className: "h-4 w-4" }) })] }), jsxRuntime.jsxs(Select, { value: condition.fieldKey, onValueChange: (value) => updateCondition(index, { fieldKey: value }), children: [jsxRuntime.jsx(SelectTrigger, { children: jsxRuntime.jsx(SelectValue, { placeholder: "Select field..." }) }), jsxRuntime.jsx(SelectContent, { children: allFields.map((f) => (jsxRuntime.jsxs(SelectItem, { value: f.props.key, children: [f.props.label, " (", f.props.key, ")"] }, f.id))) })] }), jsxRuntime.jsxs(Select, { value: condition.operator, onValueChange: (value) => updateCondition(index, { operator: value }), children: [jsxRuntime.jsx(SelectTrigger, { children: jsxRuntime.jsx(SelectValue, {}) }), jsxRuntime.jsxs(SelectContent, { children: [jsxRuntime.jsx(SelectItem, { value: "equals", children: "Equals" }), jsxRuntime.jsx(SelectItem, { value: "notEquals", children: "Not equals" }), jsxRuntime.jsx(SelectItem, { value: "contains", children: "Contains" }), jsxRuntime.jsx(SelectItem, { value: "notContains", children: "Does not contain" }), jsxRuntime.jsx(SelectItem, { value: "greaterThan", children: "Greater than" }), jsxRuntime.jsx(SelectItem, { value: "lessThan", children: "Less than" }), jsxRuntime.jsx(SelectItem, { value: "isEmpty", children: "Is empty" }), jsxRuntime.jsx(SelectItem, { value: "isNotEmpty", children: "Is not empty" }), jsxRuntime.jsx(SelectItem, { value: "startsWith", children: "Starts with" }), jsxRuntime.jsx(SelectItem, { value: "endsWith", children: "Ends with" })] })] }), !['isEmpty', 'isNotEmpty'].includes(condition.operator) && (jsxRuntime.jsx(Input, { value: condition.value || '', onChange: (e) => updateCondition(index, { value: e.target.value }), placeholder: "Value..." }))] }, index))), jsxRuntime.jsxs(Button, { variant: "outline", size: "sm", onClick: addCondition, className: "w-full gap-2", children: [jsxRuntime.jsx(Plus, { className: "h-4 w-4" }), "Add Condition"] })] })] }))] }));
|
|
19883
|
-
})() }), jsxRuntime.jsxs(TabsContent, { value: "actions", className: "space-y-4 mt-0", children: [jsxRuntime.jsxs("div", { className: "flex items-center gap-2 mb-4", children: [jsxRuntime.jsx(MousePointerClick, { className: "h-4 w-4 text-muted-foreground" }), jsxRuntime.jsx("span", { className: "text-sm font-medium", children: "Event Handlers" })] }), jsxRuntime.jsx("p", { className: "text-xs text-muted-foreground mb-4", children: "Add actions that trigger on specific events like click, change, focus, or blur." }), ['onClick', 'onChange', 'onFocus', 'onBlur'].map((eventType) => (jsxRuntime.jsxs(Collapsible, { className: "border border-border rounded-md", children: [jsxRuntime.jsxs(CollapsibleTrigger, { className: "flex items-center justify-between w-full p-3 hover:bg-muted/50", children: [jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [jsxRuntime.jsx(Play, { className: "h-3 w-3 text-muted-foreground" }), jsxRuntime.jsx("span", { className: "text-sm font-medium", children: eventType }), (field.events?.[eventType]?.length || 0) > 0 && (jsxRuntime.jsx(Badge, { variant: "secondary", className: "text-xs", children: field.events?.[eventType]?.length }))] }), jsxRuntime.jsx(ChevronDown, { className: "h-4 w-4 text-muted-foreground" })] }), jsxRuntime.jsxs(CollapsibleContent, { className: "p-3 pt-0 space-y-3", children: [(field.events?.[eventType] || []).map((action, index) => (jsxRuntime.jsxs("div", { className: "p-3 border border-border rounded-md space-y-3 bg-muted/30", children: [jsxRuntime.jsxs("div", { className: "flex items-center justify-between", children: [jsxRuntime.jsxs(Badge, { variant: "outline", children: ["Action ", index + 1] }), jsxRuntime.jsx(Button, { variant: "ghost", size: "icon", onClick: () => removeEventAction(eventType, index), children: jsxRuntime.jsx(Trash2, { className: "h-4 w-4" }) })] }), jsxRuntime.jsxs("div", { className: "space-y-2", children: [jsxRuntime.jsx(Label$2, { className: "text-xs", children: "Type" }), jsxRuntime.jsxs(Select, { value: action.type, onValueChange: (value) => updateEventAction(eventType, index, { type: value }), children: [jsxRuntime.jsx(SelectTrigger, { children: jsxRuntime.jsx(SelectValue, {}) }), jsxRuntime.jsxs(SelectContent, { children: [jsxRuntime.jsx(SelectItem, { value: "common", children: "Common Action" }), jsxRuntime.jsx(SelectItem, { value: "code", children: "Code Action" }), jsxRuntime.jsx(SelectItem, { value: "custom", children: "Custom Action" })] })] })] }), action.type === 'common' && (jsxRuntime.jsxs("div", { className: "space-y-2", children: [jsxRuntime.jsx(Label$2, { className: "text-xs", children: "Action" }), jsxRuntime.jsxs(Select, { value: action.name, onValueChange: (value) => updateEventAction(eventType, index, { name: value }), children: [jsxRuntime.jsx(SelectTrigger, { children: jsxRuntime.jsx(SelectValue, { placeholder: "Select action..." }) }), jsxRuntime.jsxs(SelectContent, { children: [jsxRuntime.jsx(SelectItem, { value: "validate", children: "Validate Form" }), jsxRuntime.jsx(SelectItem, { value: "reset", children: "Reset Form" }), jsxRuntime.jsx(SelectItem, { value: "submit", children: "Submit Form" }), jsxRuntime.jsx(SelectItem, { value: "clearField", children: "Clear This Field" }), jsxRuntime.jsx(SelectItem, { value: "focusField", children: "Focus Field" }), jsxRuntime.jsx(SelectItem, { value: "showMessage", children: "Show Message" })] })] })] })), action.type === 'code' && (jsxRuntime.jsxs("div", { className: "space-y-2", children: [jsxRuntime.jsx(Label$2, { className: "text-xs", children: "JavaScript Code" }), jsxRuntime.jsx(Textarea, { value: action.code || '', onChange: (e) => updateEventAction(eventType, index, { code: e.target.value }), placeholder: "console.log('Action triggered');", className: "font-mono text-xs min-h-[60px]" })] })), action.type === 'custom' && (jsxRuntime.jsxs("div", { className: "space-y-2", children: [jsxRuntime.jsx(Label$2, { className: "text-xs", children: "Custom Action Name" }), jsxRuntime.jsx(Input, { value: action.name, onChange: (e) => updateEventAction(eventType, index, { name: e.target.value }), placeholder: "myCustomAction", className: "font-mono text-sm" }), jsxRuntime.jsx("p", { className: "text-xs text-muted-foreground", children: "This will call the custom action passed to FormViewer" })] }))] }, index))), jsxRuntime.jsxs(Button, { variant: "outline", size: "sm", onClick: () => addEventAction(eventType), className: "w-full gap-2", children: [jsxRuntime.jsx(Plus, { className: "h-4 w-4" }), "Add Action"] })] })] }, eventType)))] }), jsxRuntime.jsxs(TabsContent, { value: "style", className: "space-y-4 mt-0", children: [jsxRuntime.jsxs("div", { className: "flex items-center justify-between mb-4", children: [jsxRuntime.jsx("span", { className: "text-sm font-medium", children: "For device" }), jsxRuntime.jsxs(Select, { value: field.customStyle?.deviceTarget || 'any', onValueChange: (value) => handleUpdateCustomStyle('deviceTarget', value), children: [jsxRuntime.jsx(SelectTrigger, { className: "w-32", children: jsxRuntime.jsx(SelectValue, {}) }), jsxRuntime.jsxs(SelectContent, { children: [jsxRuntime.jsx(SelectItem, { value: "any", children: "Any" }), jsxRuntime.jsx(SelectItem, { value: "mobile", children: "Mobile" }), jsxRuntime.jsx(SelectItem, { value: "tablet", children: "Tablet" }), jsxRuntime.jsx(SelectItem, { value: "desktop", children: "Desktop" })] })] })] }), jsxRuntime.jsxs("div", { className: "space-y-4", children: [jsxRuntime.jsx("h4", { className: "text-sm font-semibold", children: "Component" }), jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [jsxRuntime.jsx(Paintbrush, { className: "h-4 w-4 text-muted-foreground" }), jsxRuntime.jsx(Label$2, { className: "text-sm w-24", children: "Class Name" }), jsxRuntime.jsx(Input, { value: field.customStyle?.inputClassName || '', onChange: (e) => handleUpdateCustomStyle('inputClassName', e.target.value), placeholder: "", className: "font-mono text-sm flex-1" }), field.customStyle?.inputClassName && (jsxRuntime.jsx(Button, { variant: "ghost", size: "icon", onClick: () => handleUpdateCustomStyle('inputClassName', ''), children: jsxRuntime.jsx(Trash2, { className: "h-4 w-4" }) }))] })] }), jsxRuntime.jsx(Separator$1, {}), jsxRuntime.jsxs("div", { className: "space-y-4", children: [jsxRuntime.jsx("h4", { className: "text-sm font-semibold", children: "Wrapper" }), jsxRuntime.jsxs("div", { className: "grid grid-cols-2 gap-3", children: [jsxRuntime.jsxs("div", { className: "space-y-1", children: [jsxRuntime.jsx(Label$2, { className: "text-xs", children: "Width" }), jsxRuntime.jsxs("div", { className: "flex gap-1", children: [jsxRuntime.jsx(Input, { type: "number", value: field.customStyle?.width?.value ?? 100, onChange: (e) => handleUpdateCustomStyle('width', {
|
|
20015
|
+
})() }), jsxRuntime.jsxs(TabsContent, { value: "actions", className: "space-y-4 mt-0", children: [jsxRuntime.jsxs("div", { className: "flex items-center gap-2 mb-4", children: [jsxRuntime.jsx(MousePointerClick, { className: "h-4 w-4 text-muted-foreground" }), jsxRuntime.jsx("span", { className: "text-sm font-medium", children: "Event Handlers" })] }), jsxRuntime.jsx("p", { className: "text-xs text-muted-foreground mb-4", children: "Add actions that trigger on specific events like click, change, focus, or blur." }), ['onClick', 'onChange', 'onFocus', 'onBlur'].map((eventType) => (jsxRuntime.jsxs(Collapsible, { className: "border border-border rounded-md", children: [jsxRuntime.jsxs(CollapsibleTrigger, { className: "flex items-center justify-between w-full p-3 hover:bg-muted/50", children: [jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [jsxRuntime.jsx(Play, { className: "h-3 w-3 text-muted-foreground" }), jsxRuntime.jsx("span", { className: "text-sm font-medium", children: eventType }), (field.events?.[eventType]?.length || 0) > 0 && (jsxRuntime.jsx(Badge, { variant: "secondary", className: "text-xs", children: field.events?.[eventType]?.length }))] }), jsxRuntime.jsx(ChevronDown, { className: "h-4 w-4 text-muted-foreground" })] }), jsxRuntime.jsxs(CollapsibleContent, { className: "p-3 pt-0 space-y-3", children: [(field.events?.[eventType] || []).map((action, index) => (jsxRuntime.jsxs("div", { className: "p-3 border border-border rounded-md space-y-3 bg-muted/30", children: [jsxRuntime.jsxs("div", { className: "flex items-center justify-between", children: [jsxRuntime.jsxs(Badge, { variant: "outline", children: ["Action ", index + 1] }), jsxRuntime.jsx(Button, { variant: "ghost", size: "icon", onClick: () => removeEventAction(eventType, index), children: jsxRuntime.jsx(Trash2, { className: "h-4 w-4" }) })] }), jsxRuntime.jsxs("div", { className: "space-y-2", children: [jsxRuntime.jsx(Label$2, { className: "text-xs", children: "Type" }), jsxRuntime.jsxs(Select, { value: action.type, onValueChange: (value) => updateEventAction(eventType, index, { type: value }), children: [jsxRuntime.jsx(SelectTrigger, { children: jsxRuntime.jsx(SelectValue, {}) }), jsxRuntime.jsxs(SelectContent, { children: [jsxRuntime.jsx(SelectItem, { value: "common", children: "Common Action" }), jsxRuntime.jsx(SelectItem, { value: "code", children: "Code Action" }), jsxRuntime.jsx(SelectItem, { value: "custom", children: "Custom Action" })] })] })] }), action.type === 'common' && (jsxRuntime.jsxs("div", { className: "space-y-2", children: [jsxRuntime.jsx(Label$2, { className: "text-xs", children: "Action" }), jsxRuntime.jsxs(Select, { value: action.name, onValueChange: (value) => updateEventAction(eventType, index, { name: value }), children: [jsxRuntime.jsx(SelectTrigger, { children: jsxRuntime.jsx(SelectValue, { placeholder: "Select action..." }) }), jsxRuntime.jsxs(SelectContent, { children: [jsxRuntime.jsx(SelectItem, { value: "validate", children: "Validate Form" }), jsxRuntime.jsx(SelectItem, { value: "reset", children: "Reset Form" }), jsxRuntime.jsx(SelectItem, { value: "submit", children: "Submit Form" }), jsxRuntime.jsx(SelectItem, { value: "clearField", children: "Clear This Field" }), jsxRuntime.jsx(SelectItem, { value: "focusField", children: "Focus Field" }), jsxRuntime.jsx(SelectItem, { value: "showMessage", children: "Show Message" })] })] }), action.name === 'focusField' && (jsxRuntime.jsxs("div", { className: "space-y-2 mt-2", children: [jsxRuntime.jsx(Label$2, { className: "text-xs", children: "Target Field" }), jsxRuntime.jsxs(Select, { value: action.args?.targetFieldKey || '', onValueChange: (value) => updateEventAction(eventType, index, { args: { ...action.args, targetFieldKey: value } }), children: [jsxRuntime.jsx(SelectTrigger, { children: jsxRuntime.jsx(SelectValue, { placeholder: "Select field to focus..." }) }), jsxRuntime.jsx(SelectContent, { children: allFields.map((f) => (jsxRuntime.jsx(SelectItem, { value: f.props.key, children: f.props.label || f.props.key }, f.id))) })] })] })), action.name === 'showMessage' && (jsxRuntime.jsxs("div", { className: "space-y-2 mt-2", children: [jsxRuntime.jsx(Label$2, { className: "text-xs", children: "Message" }), jsxRuntime.jsx(Input, { value: action.args?.message || '', onChange: (e) => updateEventAction(eventType, index, { args: { ...action.args, message: e.target.value } }), placeholder: "Enter message to show..." })] }))] })), action.type === 'code' && (jsxRuntime.jsxs("div", { className: "space-y-2", children: [jsxRuntime.jsx(Label$2, { className: "text-xs", children: "JavaScript Code" }), jsxRuntime.jsx(Textarea, { value: action.code || '', onChange: (e) => updateEventAction(eventType, index, { code: e.target.value }), placeholder: "console.log('Action triggered');", className: "font-mono text-xs min-h-[60px]" })] })), action.type === 'custom' && (jsxRuntime.jsxs("div", { className: "space-y-2", children: [jsxRuntime.jsx(Label$2, { className: "text-xs", children: "Custom Action Name" }), jsxRuntime.jsx(Input, { value: action.name, onChange: (e) => updateEventAction(eventType, index, { name: e.target.value }), placeholder: "myCustomAction", className: "font-mono text-sm" }), jsxRuntime.jsx("p", { className: "text-xs text-muted-foreground", children: "This will call the custom action passed to FormViewer" })] }))] }, index))), jsxRuntime.jsxs(Button, { variant: "outline", size: "sm", onClick: () => addEventAction(eventType), className: "w-full gap-2", children: [jsxRuntime.jsx(Plus, { className: "h-4 w-4" }), "Add Action"] })] })] }, eventType)))] }), jsxRuntime.jsxs(TabsContent, { value: "style", className: "space-y-4 mt-0", children: [jsxRuntime.jsxs("div", { className: "flex items-center justify-between mb-4", children: [jsxRuntime.jsx("span", { className: "text-sm font-medium", children: "For device" }), jsxRuntime.jsxs(Select, { value: field.customStyle?.deviceTarget || 'any', onValueChange: (value) => handleUpdateCustomStyle('deviceTarget', value), children: [jsxRuntime.jsx(SelectTrigger, { className: "w-32", children: jsxRuntime.jsx(SelectValue, {}) }), jsxRuntime.jsxs(SelectContent, { children: [jsxRuntime.jsx(SelectItem, { value: "any", children: "Any" }), jsxRuntime.jsx(SelectItem, { value: "mobile", children: "Mobile" }), jsxRuntime.jsx(SelectItem, { value: "tablet", children: "Tablet" }), jsxRuntime.jsx(SelectItem, { value: "desktop", children: "Desktop" })] })] })] }), jsxRuntime.jsxs("div", { className: "space-y-4", children: [jsxRuntime.jsx("h4", { className: "text-sm font-semibold", children: "Component" }), jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [jsxRuntime.jsx(Paintbrush, { className: "h-4 w-4 text-muted-foreground" }), jsxRuntime.jsx(Label$2, { className: "text-sm w-24", children: "Class Name" }), jsxRuntime.jsx(Input, { value: field.customStyle?.inputClassName || '', onChange: (e) => handleUpdateCustomStyle('inputClassName', e.target.value), placeholder: "", className: "font-mono text-sm flex-1" }), field.customStyle?.inputClassName && (jsxRuntime.jsx(Button, { variant: "ghost", size: "icon", onClick: () => handleUpdateCustomStyle('inputClassName', ''), children: jsxRuntime.jsx(Trash2, { className: "h-4 w-4" }) }))] })] }), jsxRuntime.jsx(Separator$1, {}), jsxRuntime.jsxs("div", { className: "space-y-4", children: [jsxRuntime.jsx("h4", { className: "text-sm font-semibold", children: "Wrapper" }), jsxRuntime.jsxs("div", { className: "grid grid-cols-2 gap-3", children: [jsxRuntime.jsxs("div", { className: "space-y-1", children: [jsxRuntime.jsx(Label$2, { className: "text-xs", children: "Width" }), jsxRuntime.jsxs("div", { className: "flex gap-1", children: [jsxRuntime.jsx(Input, { type: "number", value: field.customStyle?.width?.value ?? 100, onChange: (e) => handleUpdateCustomStyle('width', {
|
|
19884
20016
|
...field.customStyle?.width,
|
|
19885
20017
|
value: parseInt(e.target.value) || 100
|
|
19886
20018
|
}), className: "w-16" }), jsxRuntime.jsxs(Select, { value: field.customStyle?.width?.unit || '%', onValueChange: (value) => handleUpdateCustomStyle('width', {
|
|
@@ -25054,12 +25186,12 @@ function DraggableComponent({ type, label, icon, isCollapsed }) {
|
|
|
25054
25186
|
}
|
|
25055
25187
|
const fieldCategories = {
|
|
25056
25188
|
basic: { label: 'Basic Fields', types: FIELD_TYPES.filter(f => f.category === 'basic') },
|
|
25057
|
-
selection: { label: 'Selection Fields', types: FIELD_TYPES.filter(f => f.category === 'selection') },
|
|
25058
25189
|
advanced: { label: 'Advanced Fields', types: FIELD_TYPES.filter(f => f.category === 'advanced') },
|
|
25190
|
+
selection: { label: 'Selection Fields', types: FIELD_TYPES.filter(f => f.category === 'selection') },
|
|
25059
25191
|
};
|
|
25060
25192
|
function ComponentLibrary({ isCollapsed = false, onToggleCollapse }) {
|
|
25061
25193
|
if (isCollapsed) {
|
|
25062
|
-
return (jsxRuntime.jsxs("aside", { className: "w-[60px] border-r border-border bg-card shrink-0 flex flex-col", children: [jsxRuntime.jsx("div", { className: "p-2 border-b border-border", children: jsxRuntime.jsx(Button, { variant: "ghost", size: "icon", onClick: onToggleCollapse, "data-testid": "button-expand-sidebar", children: jsxRuntime.jsx(PanelLeft, { className: "h-4 w-4" }) }) }), jsxRuntime.jsx(ScrollArea, { className: "flex-1", children: jsxRuntime.jsxs("div", { className: "p-2 space-y-4", children: [jsxRuntime.jsxs("div", { className: "space-y-1", children: [jsxRuntime.jsxs(Tooltip, { children: [jsxRuntime.jsx(TooltipTrigger, { asChild: true, children: jsxRuntime.jsx("p", { className: "text-[10px] font-semibold uppercase text-muted-foreground text-center cursor-default", children: "LY" }) }), jsxRuntime.jsx(TooltipContent, { side: "right", children: "Layout" })] }), jsxRuntime.jsx("div", { className: "grid grid-cols-1 gap-1", children: STRUCTURE_TYPES.map((item) => (jsxRuntime.jsx(DraggableComponent, { type: item.type, label: item.label, icon: item.icon, isCollapsed: true }, item.type))) })] }), jsxRuntime.jsxs("div", { className: "space-y-1", children: [jsxRuntime.jsxs(Tooltip, { children: [jsxRuntime.jsx(TooltipTrigger, { asChild: true, children: jsxRuntime.jsx("p", { className: "text-[10px] font-semibold uppercase text-muted-foreground text-center cursor-default", children: "BF" }) }), jsxRuntime.jsx(TooltipContent, { side: "right", children: "Basic Fields" })] }), jsxRuntime.jsx("div", { className: "grid grid-cols-1 gap-1", children: fieldCategories.basic.types.map((item) => (jsxRuntime.jsx(DraggableComponent, { type: item.type, label: item.label, icon: item.icon, isCollapsed: true }, item.type))) })] }), jsxRuntime.jsxs("div", { className: "space-y-1", children: [jsxRuntime.jsxs(Tooltip, { children: [jsxRuntime.jsx(TooltipTrigger, { asChild: true, children: jsxRuntime.jsx("p", { className: "text-[10px] font-semibold uppercase text-muted-foreground text-center cursor-default", children: "
|
|
25194
|
+
return (jsxRuntime.jsxs("aside", { className: "w-[60px] border-r border-border bg-card shrink-0 flex flex-col", children: [jsxRuntime.jsx("div", { className: "p-2 border-b border-border", children: jsxRuntime.jsx(Button, { variant: "ghost", size: "icon", onClick: onToggleCollapse, "data-testid": "button-expand-sidebar", children: jsxRuntime.jsx(PanelLeft, { className: "h-4 w-4" }) }) }), jsxRuntime.jsx(ScrollArea, { className: "flex-1", children: jsxRuntime.jsxs("div", { className: "p-2 space-y-4", children: [jsxRuntime.jsxs("div", { className: "space-y-1", children: [jsxRuntime.jsxs(Tooltip, { children: [jsxRuntime.jsx(TooltipTrigger, { asChild: true, children: jsxRuntime.jsx("p", { className: "text-[10px] font-semibold uppercase text-muted-foreground text-center cursor-default", children: "LY" }) }), jsxRuntime.jsx(TooltipContent, { side: "right", children: "Layout" })] }), jsxRuntime.jsx("div", { className: "grid grid-cols-1 gap-1", children: STRUCTURE_TYPES.map((item) => (jsxRuntime.jsx(DraggableComponent, { type: item.type, label: item.label, icon: item.icon, isCollapsed: true }, item.type))) })] }), jsxRuntime.jsxs("div", { className: "space-y-1", children: [jsxRuntime.jsxs(Tooltip, { children: [jsxRuntime.jsx(TooltipTrigger, { asChild: true, children: jsxRuntime.jsx("p", { className: "text-[10px] font-semibold uppercase text-muted-foreground text-center cursor-default", children: "BF" }) }), jsxRuntime.jsx(TooltipContent, { side: "right", children: "Basic Fields" })] }), jsxRuntime.jsx("div", { className: "grid grid-cols-1 gap-1", children: fieldCategories.basic.types.map((item) => (jsxRuntime.jsx(DraggableComponent, { type: item.type, label: item.label, icon: item.icon, isCollapsed: true }, item.type))) })] }), jsxRuntime.jsxs("div", { className: "space-y-1", children: [jsxRuntime.jsxs(Tooltip, { children: [jsxRuntime.jsx(TooltipTrigger, { asChild: true, children: jsxRuntime.jsx("p", { className: "text-[10px] font-semibold uppercase text-muted-foreground text-center cursor-default", children: "AD" }) }), jsxRuntime.jsx(TooltipContent, { side: "right", children: "Advanced Fields" })] }), jsxRuntime.jsx("div", { className: "grid grid-cols-1 gap-1", children: fieldCategories.advanced.types.map((item) => (jsxRuntime.jsx(DraggableComponent, { type: item.type, label: item.label, icon: item.icon, isCollapsed: true }, item.type))) })] }), jsxRuntime.jsxs("div", { className: "space-y-1", children: [jsxRuntime.jsxs(Tooltip, { children: [jsxRuntime.jsx(TooltipTrigger, { asChild: true, children: jsxRuntime.jsx("p", { className: "text-[10px] font-semibold uppercase text-muted-foreground text-center cursor-default", children: "SF" }) }), jsxRuntime.jsx(TooltipContent, { side: "right", children: "Selection Fields" })] }), jsxRuntime.jsx("div", { className: "grid grid-cols-1 gap-1", children: fieldCategories.selection.types.map((item) => (jsxRuntime.jsx(DraggableComponent, { type: item.type, label: item.label, icon: item.icon, isCollapsed: true }, item.type))) })] }), jsxRuntime.jsxs("div", { className: "space-y-1", children: [jsxRuntime.jsxs(Tooltip, { children: [jsxRuntime.jsx(TooltipTrigger, { asChild: true, children: jsxRuntime.jsx("p", { className: "text-[10px] font-semibold uppercase text-muted-foreground text-center cursor-default", children: "EL" }) }), jsxRuntime.jsx(TooltipContent, { side: "right", children: "Static Elements" })] }), jsxRuntime.jsx("div", { className: "grid grid-cols-1 gap-1", children: STATIC_TYPES.map((item) => (jsxRuntime.jsx(DraggableComponent, { type: item.type, label: item.label, icon: item.icon, isCollapsed: true }, item.type))) })] })] }) })] }));
|
|
25063
25195
|
}
|
|
25064
25196
|
return (jsxRuntime.jsxs("aside", { className: "w-[200px] border-r border-border bg-card shrink-0 flex flex-col", children: [jsxRuntime.jsxs("div", { className: "p-2 border-b border-border flex items-center justify-between gap-2", children: [jsxRuntime.jsx("span", { className: "text-sm font-medium text-foreground pl-1", children: "Components" }), jsxRuntime.jsx(Button, { variant: "ghost", size: "icon", className: "h-6 w-6 shrink-0", onClick: onToggleCollapse, "data-testid": "button-collapse-sidebar", children: jsxRuntime.jsx(PanelLeftClose, { className: "h-3.5 w-3.5" }) })] }), jsxRuntime.jsx(ScrollArea, { className: "flex-1", children: jsxRuntime.jsx("div", { className: "p-2", children: jsxRuntime.jsxs(Accordion, { type: "multiple", defaultValue: ['structure', 'basic', 'selection', 'advanced', 'static'], className: "w-full", children: [jsxRuntime.jsxs(AccordionItem, { value: "structure", className: "border-b-0 bg-muted/50 rounded-md mb-1 px-2", children: [jsxRuntime.jsxs(AccordionTrigger, { className: "py-1.5 text-[10px] font-semibold uppercase tracking-wide text-muted-foreground hover:no-underline", children: ["Layout (", STRUCTURE_TYPES.length, ")"] }), jsxRuntime.jsx(AccordionContent, { children: jsxRuntime.jsx("div", { className: "grid grid-cols-2 gap-1 pb-2", children: STRUCTURE_TYPES.map((item) => (jsxRuntime.jsx(DraggableComponent, { type: item.type, label: item.label, icon: item.icon }, item.type))) }) })] }), Object.entries(fieldCategories).map(([key, category]) => (jsxRuntime.jsxs(AccordionItem, { value: key, className: "border-b-0 bg-background dark:bg-card rounded-md mb-1 px-2", children: [jsxRuntime.jsxs(AccordionTrigger, { className: "py-1.5 text-[10px] font-semibold uppercase tracking-wide text-muted-foreground hover:no-underline", children: [category.label.split(' ')[0], " (", category.types.length, ")"] }), jsxRuntime.jsx(AccordionContent, { children: jsxRuntime.jsx("div", { className: "grid grid-cols-2 gap-1 pb-2", children: category.types.map((item) => (jsxRuntime.jsx(DraggableComponent, { type: item.type, label: item.label, icon: item.icon }, item.type))) }) })] }, key))), jsxRuntime.jsxs(AccordionItem, { value: "static", className: "border-b-0 bg-background dark:bg-card rounded-md mb-1 px-2", children: [jsxRuntime.jsxs(AccordionTrigger, { className: "py-1.5 text-[10px] font-semibold uppercase tracking-wide text-muted-foreground hover:no-underline", children: ["Attributes (", STATIC_TYPES.length, ")"] }), jsxRuntime.jsx(AccordionContent, { children: jsxRuntime.jsx("div", { className: "grid grid-cols-2 gap-1 pb-2", children: STATIC_TYPES.map((item) => (jsxRuntime.jsx(DraggableComponent, { type: item.type, label: item.label, icon: item.icon }, item.type))) }) })] })] }) }) })] }));
|
|
25065
25197
|
}
|
|
@@ -28343,7 +28475,9 @@ const DropdownMenuSeparator = React__namespace.forwardRef(({ className, ...props
|
|
|
28343
28475
|
DropdownMenuSeparator.displayName = Separator2.displayName;
|
|
28344
28476
|
|
|
28345
28477
|
function Toolbar({ onOpenJsonViewer }) {
|
|
28346
|
-
const { form, setFormName, isPreviewMode, togglePreviewMode, clearForm, toggleMultiStep, saveVersion, restoreVersion, updateSubmissionConfig, undo, redo,
|
|
28478
|
+
const { form, setFormName, isPreviewMode, togglePreviewMode, clearForm, toggleMultiStep, saveVersion, restoreVersion, updateSubmissionConfig, undo, redo, canvasWidth, setCanvasWidth, historyIndex, history, } = useFormStore();
|
|
28479
|
+
const canUndo = historyIndex > 0;
|
|
28480
|
+
const canRedo = historyIndex < history.length - 1;
|
|
28347
28481
|
const widthOptions = [
|
|
28348
28482
|
{ value: 'compact', label: 'Compact', description: '672px' },
|
|
28349
28483
|
{ value: 'medium', label: 'Medium', description: '896px' },
|
|
@@ -28356,6 +28490,7 @@ function Toolbar({ onOpenJsonViewer }) {
|
|
|
28356
28490
|
const [versionDialogOpen, setVersionDialogOpen] = React.useState(false);
|
|
28357
28491
|
const [changelog, setChangelog] = React.useState('');
|
|
28358
28492
|
const [settingsDialogOpen, setSettingsDialogOpen] = React.useState(false);
|
|
28493
|
+
const [docsDialogOpen, setDocsDialogOpen] = React.useState(false);
|
|
28359
28494
|
const [isDarkMode, setIsDarkMode] = React.useState(false);
|
|
28360
28495
|
const { toast } = useToast();
|
|
28361
28496
|
const toggleTheme = () => {
|
|
@@ -28452,7 +28587,101 @@ function Toolbar({ onOpenJsonViewer }) {
|
|
|
28452
28587
|
return (jsxRuntime.jsxs("header", { className: "h-14 border-b border-border bg-card px-6 flex items-center justify-between gap-4 shrink-0", children: [jsxRuntime.jsx("div", { className: "flex items-center gap-3", children: isEditing ? (jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [jsxRuntime.jsx(Input, { value: tempName, onChange: (e) => setTempName(e.target.value), onKeyDown: handleKeyDown, onBlur: handleSaveName, className: "h-8 w-64 text-sm font-medium", autoFocus: true, "data-testid": "input-form-name" }), jsxRuntime.jsx(Button, { size: "icon", variant: "ghost", onClick: handleSaveName, "data-testid": "button-save-name", children: jsxRuntime.jsx(Check, { className: "h-4 w-4" }) })] })) : (jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [jsxRuntime.jsx("h1", { className: "text-lg font-semibold text-foreground", children: form.name }), jsxRuntime.jsx(Button, { size: "icon", variant: "ghost", onClick: () => {
|
|
28453
28588
|
setTempName(form.name);
|
|
28454
28589
|
setIsEditing(true);
|
|
28455
|
-
}, "data-testid": "button-edit-name", children: jsxRuntime.jsx(PenLine, { className: "h-4 w-4" }) }), form.isMultiStep && (jsxRuntime.jsx(Badge, { variant: "secondary", className: "text-xs", children: "Multi-Step" })), form.currentVersion && (jsxRuntime.jsxs(Badge, { variant: "outline", className: "text-xs", children: ["v", form.currentVersion] }))] })) }), jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [jsxRuntime.jsxs(Tooltip, { children: [jsxRuntime.jsx(TooltipTrigger, { asChild: true, children: jsxRuntime.jsx(Button, { variant: "ghost", size: "icon", onClick: undo, disabled: !canUndo
|
|
28590
|
+
}, "data-testid": "button-edit-name", children: jsxRuntime.jsx(PenLine, { className: "h-4 w-4" }) }), form.isMultiStep && (jsxRuntime.jsx(Badge, { variant: "secondary", className: "text-xs", children: "Multi-Step" })), form.currentVersion && (jsxRuntime.jsxs(Badge, { variant: "outline", className: "text-xs", children: ["v", form.currentVersion] }))] })) }), jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [jsxRuntime.jsxs(Tooltip, { children: [jsxRuntime.jsx(TooltipTrigger, { asChild: true, children: jsxRuntime.jsx(Button, { variant: "ghost", size: "icon", onClick: undo, disabled: !canUndo, "data-testid": "button-undo", children: jsxRuntime.jsx(Undo2, { className: "h-4 w-4" }) }) }), jsxRuntime.jsx(TooltipContent, { children: "Undo" })] }), jsxRuntime.jsxs(Tooltip, { children: [jsxRuntime.jsx(TooltipTrigger, { asChild: true, children: jsxRuntime.jsx(Button, { variant: "ghost", size: "icon", onClick: redo, disabled: !canRedo, "data-testid": "button-redo", children: jsxRuntime.jsx(Redo2, { className: "h-4 w-4" }) }) }), jsxRuntime.jsx(TooltipContent, { children: "Redo" })] }), jsxRuntime.jsxs(DropdownMenu, { children: [jsxRuntime.jsxs(Tooltip, { children: [jsxRuntime.jsx(TooltipTrigger, { asChild: true, children: jsxRuntime.jsx(DropdownMenuTrigger, { asChild: true, children: jsxRuntime.jsx(Button, { variant: "ghost", size: "icon", "data-testid": "button-canvas-width", children: jsxRuntime.jsx(Maximize2, { className: "h-4 w-4" }) }) }) }), jsxRuntime.jsx(TooltipContent, { children: "Canvas Width" })] }), jsxRuntime.jsxs(DropdownMenuContent, { align: "end", children: [jsxRuntime.jsx(DropdownMenuLabel, { children: "Canvas Width" }), jsxRuntime.jsx(DropdownMenuSeparator, {}), widthOptions.map((option) => (jsxRuntime.jsxs(DropdownMenuItem, { onClick: () => setCanvasWidth(option.value), className: "flex justify-between gap-4", "data-testid": `menu-width-${option.value}`, children: [jsxRuntime.jsx("span", { children: option.label }), jsxRuntime.jsx("span", { className: "text-muted-foreground text-xs", children: option.description }), canvasWidth === option.value && jsxRuntime.jsx(Check, { className: "h-4 w-4 ml-2" })] }, option.value)))] })] }), jsxRuntime.jsx("div", { className: "w-px h-6 bg-border mx-1" }), jsxRuntime.jsxs(Button, { variant: "default", size: "sm", onClick: handleSaveForm, disabled: isSaving, className: "gap-2", "data-testid": "button-save-form", children: [isSaving ? (jsxRuntime.jsx(LoaderCircle, { className: "h-4 w-4 animate-spin" })) : (jsxRuntime.jsx(Save, { className: "h-4 w-4" })), jsxRuntime.jsx("span", { children: "Save" })] }), jsxRuntime.jsx(Button, { variant: isPreviewMode ? 'default' : 'outline', size: "sm", onClick: togglePreviewMode, className: "gap-2", "data-testid": "button-toggle-preview", children: isPreviewMode ? (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsx(EyeOff, { className: "h-4 w-4" }), jsxRuntime.jsx("span", { children: "Edit" })] })) : (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsx(Eye, { className: "h-4 w-4" }), jsxRuntime.jsx("span", { children: "Preview" })] })) }), jsxRuntime.jsx(Button, { variant: form.isMultiStep ? 'default' : 'outline', size: "sm", onClick: toggleMultiStep, className: "gap-2", title: form.isMultiStep ? 'Switch to single page' : 'Switch to multi-step wizard', "data-testid": "button-toggle-multistep", children: jsxRuntime.jsx(Layers, { className: "h-4 w-4" }) }), jsxRuntime.jsxs(Dialog, { open: versionDialogOpen, onOpenChange: setVersionDialogOpen, children: [jsxRuntime.jsx(DialogTrigger, { asChild: true, children: jsxRuntime.jsx(Button, { variant: "outline", size: "sm", className: "gap-2", "data-testid": "button-version", children: jsxRuntime.jsx(History, { className: "h-4 w-4" }) }) }), jsxRuntime.jsxs(DialogContent, { className: "max-w-md", children: [jsxRuntime.jsxs(DialogHeader, { children: [jsxRuntime.jsx(DialogTitle, { children: "Version History" }), jsxRuntime.jsx(DialogDescription, { children: "Save snapshots and restore previous versions of your form." })] }), jsxRuntime.jsxs("div", { className: "space-y-4", children: [jsxRuntime.jsxs("div", { className: "space-y-2", children: [jsxRuntime.jsx(Label$2, { children: "Save New Version" }), jsxRuntime.jsx(Textarea, { value: changelog, onChange: (e) => setChangelog(e.target.value), placeholder: "What changed in this version?", className: "min-h-[60px]" }), jsxRuntime.jsxs(Button, { onClick: handleSaveVersion, className: "w-full gap-2", size: "sm", children: [jsxRuntime.jsx(Save, { className: "h-4 w-4" }), "Save Version ", (form.currentVersion || 0) + 1] })] }), form.versions && form.versions.length > 0 && (jsxRuntime.jsx(jsxRuntime.Fragment, { children: jsxRuntime.jsxs("div", { className: "border-t pt-4", children: [jsxRuntime.jsx(Label$2, { className: "mb-2 block", children: "Previous Versions" }), jsxRuntime.jsx(ScrollArea, { className: "h-[200px]", children: jsxRuntime.jsx("div", { className: "space-y-2", children: [...form.versions].reverse().map((version) => (jsxRuntime.jsxs("div", { className: "p-3 border rounded-md space-y-2", children: [jsxRuntime.jsxs("div", { className: "flex items-center justify-between", children: [jsxRuntime.jsxs("span", { className: "font-medium", children: ["Version ", version.version] }), jsxRuntime.jsx(Button, { variant: "outline", size: "sm", onClick: () => handleRestoreVersion(version.id, version.version), children: "Restore" })] }), version.changelog && (jsxRuntime.jsx("p", { className: "text-sm text-muted-foreground", children: version.changelog })), jsxRuntime.jsx("p", { className: "text-xs text-muted-foreground", children: new Date(version.createdAt).toLocaleString() })] }, version.id))) }) })] }) }))] })] })] }), jsxRuntime.jsxs(Dialog, { open: docsDialogOpen, onOpenChange: setDocsDialogOpen, children: [jsxRuntime.jsxs(Tooltip, { children: [jsxRuntime.jsx(TooltipTrigger, { asChild: true, children: jsxRuntime.jsx(DialogTrigger, { asChild: true, children: jsxRuntime.jsx(Button, { variant: "outline", size: "sm", className: "gap-2", "data-testid": "button-docs", children: jsxRuntime.jsx(BookOpen, { className: "h-4 w-4" }) }) }) }), jsxRuntime.jsx(TooltipContent, { children: "Documentation" })] }), jsxRuntime.jsxs(DialogContent, { className: "max-w-4xl max-h-[85vh]", children: [jsxRuntime.jsxs(DialogHeader, { children: [jsxRuntime.jsx(DialogTitle, { children: "FormBuilder Documentation" }), jsxRuntime.jsx(DialogDescription, { children: "Complete guide for the drag-and-drop form builder component" })] }), jsxRuntime.jsx(ScrollArea, { className: "h-[60vh] pr-4", children: jsxRuntime.jsxs("div", { className: "prose prose-sm dark:prose-invert max-w-none space-y-6", children: [jsxRuntime.jsxs("section", { children: [jsxRuntime.jsx("h3", { className: "text-lg font-semibold border-b pb-2", children: "Quick Start" }), jsxRuntime.jsx("pre", { className: "bg-muted p-3 rounded text-xs overflow-x-auto text-foreground", children: `import { FormBuilder } from '@enerjisaformlibrary/formbuilder-react';
|
|
28591
|
+
import '@enerjisaformlibrary/formbuilder-react/styles.css';
|
|
28592
|
+
|
|
28593
|
+
function App() {
|
|
28594
|
+
return (
|
|
28595
|
+
<FormBuilder
|
|
28596
|
+
onSave={(form) => saveToDatabase(JSON.stringify(form))}
|
|
28597
|
+
onChange={(form) => console.log('Updated:', form)}
|
|
28598
|
+
theme="light"
|
|
28599
|
+
/>
|
|
28600
|
+
);
|
|
28601
|
+
}` })] }), jsxRuntime.jsxs("section", { children: [jsxRuntime.jsx("h3", { className: "text-lg font-semibold border-b pb-2", children: "Field Types (20+)" }), jsxRuntime.jsxs("div", { className: "grid grid-cols-3 gap-2 text-sm", children: [jsxRuntime.jsxs("div", { children: [jsxRuntime.jsx("strong", { children: "Basic:" }), " input, textarea, number, email, password, phone, url"] }), jsxRuntime.jsxs("div", { children: [jsxRuntime.jsx("strong", { children: "Selection:" }), " dropdown, checkbox, radio, toggle, multiselect"] }), jsxRuntime.jsxs("div", { children: [jsxRuntime.jsx("strong", { children: "Date/Time:" }), " date, time, daterange"] }), jsxRuntime.jsxs("div", { children: [jsxRuntime.jsx("strong", { children: "Advanced:" }), " file, signature, rating, richtext, slider, color, autocomplete"] }), jsxRuntime.jsxs("div", { children: [jsxRuntime.jsx("strong", { children: "Static:" }), " header, label, paragraph, divider, spacer, alert, image"] }), jsxRuntime.jsxs("div", { children: [jsxRuntime.jsx("strong", { children: "Structure:" }), " button, qrcode, pattern, container"] })] })] }), jsxRuntime.jsxs("section", { children: [jsxRuntime.jsx("h3", { className: "text-lg font-semibold border-b pb-2", children: "Form Schema Structure" }), jsxRuntime.jsx("pre", { className: "bg-muted p-3 rounded text-xs overflow-x-auto text-foreground", children: `FormSchema {
|
|
28602
|
+
id: string;
|
|
28603
|
+
name: string;
|
|
28604
|
+
rows: FormRow[]; // Single-page mode
|
|
28605
|
+
steps?: FormStep[]; // Multi-step wizard mode
|
|
28606
|
+
isMultiStep?: boolean;
|
|
28607
|
+
submissionConfig?: { webhookUrl, successMessage, redirectUrl };
|
|
28608
|
+
}
|
|
28609
|
+
|
|
28610
|
+
FormRow → columns[] → FormColumn (width: 1-12) → fields[] → FormField` })] }), jsxRuntime.jsxs("section", { children: [jsxRuntime.jsx("h3", { className: "text-lg font-semibold border-b pb-2", children: "FormField Properties" }), jsxRuntime.jsx("pre", { className: "bg-muted p-3 rounded text-xs overflow-x-auto text-foreground", children: `FormField {
|
|
28611
|
+
id: string;
|
|
28612
|
+
type: 'input' | 'dropdown' | 'checkbox' | ...;
|
|
28613
|
+
props: {
|
|
28614
|
+
key: string; // Unique identifier for form values
|
|
28615
|
+
label?: string;
|
|
28616
|
+
placeholder?: string;
|
|
28617
|
+
defaultValue?: string;
|
|
28618
|
+
tooltip?: string; // Help text on hover
|
|
28619
|
+
autoFocus?: boolean; // Focus on preview mode
|
|
28620
|
+
hidden?: boolean;
|
|
28621
|
+
disabled?: boolean;
|
|
28622
|
+
readOnly?: boolean;
|
|
28623
|
+
size?: 'small' | 'medium' | 'large';
|
|
28624
|
+
};
|
|
28625
|
+
validation?: { required, minLength, maxLength, pattern, min, max };
|
|
28626
|
+
conditionalLogic?: { enabled, action, conditions[] };
|
|
28627
|
+
customStyle?: { containerClassName, labelClassName, inputClassName };
|
|
28628
|
+
events?: { onClick, onChange, onFocus, onBlur };
|
|
28629
|
+
}` })] }), jsxRuntime.jsxs("section", { children: [jsxRuntime.jsx("h3", { className: "text-lg font-semibold border-b pb-2", children: "Conditional Logic" }), jsxRuntime.jsx("p", { className: "text-sm text-muted-foreground mb-2", children: "Show/hide/enable/disable fields based on other field values" }), jsxRuntime.jsx("pre", { className: "bg-muted p-3 rounded text-xs overflow-x-auto text-foreground", children: `conditionalLogic: {
|
|
28630
|
+
enabled: true,
|
|
28631
|
+
action: 'show' | 'hide' | 'enable' | 'disable' | 'require',
|
|
28632
|
+
conditions: [{
|
|
28633
|
+
field: 'country', // Target field's props.key
|
|
28634
|
+
operator: 'equals' | 'notEquals' | 'contains' | 'isEmpty' | ...,
|
|
28635
|
+
value: 'USA'
|
|
28636
|
+
}],
|
|
28637
|
+
conditionLogic: 'and' | 'or' // How to combine multiple conditions
|
|
28638
|
+
}` })] }), jsxRuntime.jsxs("section", { children: [jsxRuntime.jsx("h3", { className: "text-lg font-semibold border-b pb-2", children: "Events & Actions" }), jsxRuntime.jsx("p", { className: "text-sm text-muted-foreground mb-2", children: "Execute actions on field interactions (preview mode only)" }), jsxRuntime.jsxs("div", { className: "text-sm mb-2", children: [jsxRuntime.jsx("strong", { children: "Available Actions:" }), jsxRuntime.jsxs("ul", { className: "list-disc list-inside mt-1", children: [jsxRuntime.jsxs("li", { children: [jsxRuntime.jsx("code", { children: "focusField" }), " - Focus another field (args: targetFieldKey)"] }), jsxRuntime.jsxs("li", { children: [jsxRuntime.jsx("code", { children: "clearField" }), " - Clear current field value"] }), jsxRuntime.jsxs("li", { children: [jsxRuntime.jsx("code", { children: "showMessage" }), " - Display alert (args: message)"] }), jsxRuntime.jsxs("li", { children: [jsxRuntime.jsx("code", { children: "reset" }), " - Reset all form values"] })] })] }), jsxRuntime.jsx("pre", { className: "bg-muted p-3 rounded text-xs overflow-x-auto text-foreground", children: `events: {
|
|
28639
|
+
onChange: [{
|
|
28640
|
+
type: 'common',
|
|
28641
|
+
name: 'focusField',
|
|
28642
|
+
args: { targetFieldKey: 'nextField' }
|
|
28643
|
+
}]
|
|
28644
|
+
}` })] }), jsxRuntime.jsxs("section", { children: [jsxRuntime.jsx("h3", { className: "text-lg font-semibold border-b pb-2", children: "Zustand Store API" }), jsxRuntime.jsx("pre", { className: "bg-muted p-3 rounded text-xs overflow-x-auto text-foreground", children: `import { useFormStore } from '@enerjisaformlibrary/formbuilder-react';
|
|
28645
|
+
|
|
28646
|
+
const {
|
|
28647
|
+
form, // Current FormSchema
|
|
28648
|
+
formValues, // Values in preview mode
|
|
28649
|
+
previewMode, // boolean
|
|
28650
|
+
loadForm, // Load existing form
|
|
28651
|
+
addRow, deleteRow, // Row operations
|
|
28652
|
+
addField, updateField, // Field operations
|
|
28653
|
+
setFieldValue, // Set value in preview
|
|
28654
|
+
getFormValues, // Get all form values
|
|
28655
|
+
} = useFormStore();` })] }), jsxRuntime.jsxs("section", { children: [jsxRuntime.jsx("h3", { className: "text-lg font-semibold border-b pb-2", children: "Container Fields" }), jsxRuntime.jsx("p", { className: "text-sm text-muted-foreground mb-2", children: "Group fields with nested row/column structure" }), jsxRuntime.jsx("pre", { className: "bg-muted p-3 rounded text-xs overflow-x-auto text-foreground", children: `{
|
|
28656
|
+
type: 'container',
|
|
28657
|
+
props: {
|
|
28658
|
+
key: 'addressGroup',
|
|
28659
|
+
label: 'Address',
|
|
28660
|
+
containerConfig: {
|
|
28661
|
+
rows: [{
|
|
28662
|
+
id: 'row1',
|
|
28663
|
+
columns: [
|
|
28664
|
+
{ id: 'col1', width: 6, fields: [...] },
|
|
28665
|
+
{ id: 'col2', width: 6, fields: [...] }
|
|
28666
|
+
]
|
|
28667
|
+
}]
|
|
28668
|
+
}
|
|
28669
|
+
}
|
|
28670
|
+
}` })] }), jsxRuntime.jsxs("section", { children: [jsxRuntime.jsx("h3", { className: "text-lg font-semibold border-b pb-2", children: "Multi-Step Forms" }), jsxRuntime.jsx("pre", { className: "bg-muted p-3 rounded text-xs overflow-x-auto text-foreground", children: `{
|
|
28671
|
+
isMultiStep: true,
|
|
28672
|
+
steps: [{
|
|
28673
|
+
id: 'step1',
|
|
28674
|
+
title: 'Personal Info',
|
|
28675
|
+
order: 0,
|
|
28676
|
+
rows: [...],
|
|
28677
|
+
validation: { validateOnNext: true }
|
|
28678
|
+
}, {
|
|
28679
|
+
id: 'step2',
|
|
28680
|
+
title: 'Contact',
|
|
28681
|
+
order: 1,
|
|
28682
|
+
rows: [...]
|
|
28683
|
+
}]
|
|
28684
|
+
}` })] })] }) }), jsxRuntime.jsx(DialogFooter, { children: jsxRuntime.jsx(Button, { onClick: () => setDocsDialogOpen(false), children: "Close" }) })] })] }), jsxRuntime.jsxs(Dialog, { open: settingsDialogOpen, onOpenChange: setSettingsDialogOpen, children: [jsxRuntime.jsx(DialogTrigger, { asChild: true, children: jsxRuntime.jsx(Button, { variant: "outline", size: "sm", className: "gap-2", "data-testid": "button-settings", children: jsxRuntime.jsx(Settings, { className: "h-4 w-4" }) }) }), jsxRuntime.jsxs(DialogContent, { className: "max-w-lg", children: [jsxRuntime.jsxs(DialogHeader, { children: [jsxRuntime.jsx(DialogTitle, { children: "Form Settings" }), jsxRuntime.jsx(DialogDescription, { children: "Configure submission, webhooks, and other form settings." })] }), jsxRuntime.jsx("div", { className: "space-y-6", children: jsxRuntime.jsxs("div", { className: "space-y-4", children: [jsxRuntime.jsx("h4", { className: "font-medium", children: "Submission Settings" }), jsxRuntime.jsxs("div", { className: "flex items-center justify-between", children: [jsxRuntime.jsx(Label$2, { children: "Enable Submission Handler" }), jsxRuntime.jsx(Switch, { checked: form.submissionConfig?.enabled || false, onCheckedChange: (checked) => updateSubmissionConfig({ enabled: checked }) })] }), form.submissionConfig?.enabled && (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsxs("div", { className: "space-y-2", children: [jsxRuntime.jsx(Label$2, { children: "Webhook URL" }), jsxRuntime.jsx(Input, { value: form.submissionConfig?.webhookUrl || '', onChange: (e) => updateSubmissionConfig({ webhookUrl: e.target.value }), placeholder: "https://your-api.com/webhook" })] }), jsxRuntime.jsxs("div", { className: "space-y-2", children: [jsxRuntime.jsx(Label$2, { children: "Success Message" }), jsxRuntime.jsx(Input, { value: form.submissionConfig?.successMessage || '', onChange: (e) => updateSubmissionConfig({ successMessage: e.target.value }), placeholder: "Thank you for your submission!" })] }), jsxRuntime.jsxs("div", { className: "space-y-2", children: [jsxRuntime.jsx(Label$2, { children: "Redirect URL (optional)" }), jsxRuntime.jsx(Input, { value: form.submissionConfig?.redirectUrl || '', onChange: (e) => updateSubmissionConfig({ redirectUrl: e.target.value }), placeholder: "https://your-site.com/thank-you" })] })] }))] }) }), jsxRuntime.jsx(DialogFooter, { children: jsxRuntime.jsx(Button, { onClick: () => setSettingsDialogOpen(false), children: "Done" }) })] })] }), jsxRuntime.jsxs(DropdownMenu, { children: [jsxRuntime.jsx(DropdownMenuTrigger, { asChild: true, children: jsxRuntime.jsx(Button, { variant: "outline", size: "sm", className: "gap-2", "data-testid": "button-more", children: jsxRuntime.jsx(FileJson, { className: "h-4 w-4" }) }) }), jsxRuntime.jsxs(DropdownMenuContent, { align: "end", children: [jsxRuntime.jsx(DropdownMenuLabel, { children: "Export / Import" }), jsxRuntime.jsx(DropdownMenuSeparator, {}), jsxRuntime.jsxs(DropdownMenuItem, { onClick: onOpenJsonViewer, children: [jsxRuntime.jsx(FileJson, { className: "h-4 w-4 mr-2" }), "View JSON Schema"] }), jsxRuntime.jsxs(DropdownMenuItem, { onClick: handleExportJson, children: [jsxRuntime.jsx(Download, { className: "h-4 w-4 mr-2" }), "Download JSON"] }), jsxRuntime.jsx(DropdownMenuItem, { asChild: true, children: jsxRuntime.jsxs("label", { className: "cursor-pointer flex items-center", children: [jsxRuntime.jsx(Upload, { className: "h-4 w-4 mr-2" }), "Import JSON", jsxRuntime.jsx("input", { type: "file", accept: ".json", onChange: handleImportJson, className: "hidden" })] }) })] })] }), jsxRuntime.jsx(Button, { variant: "outline", size: "sm", onClick: clearForm, className: "gap-2 text-destructive hover:text-destructive", "data-testid": "button-clear-form", children: jsxRuntime.jsx(Trash2, { className: "h-4 w-4" }) }), jsxRuntime.jsx("div", { className: "w-px h-6 bg-border mx-1" }), jsxRuntime.jsxs(Tooltip, { children: [jsxRuntime.jsx(TooltipTrigger, { asChild: true, children: jsxRuntime.jsx(Button, { variant: "ghost", size: "icon", onClick: toggleTheme, "data-testid": "button-toggle-theme", children: isDarkMode ? jsxRuntime.jsx(Sun, { className: "h-4 w-4" }) : jsxRuntime.jsx(Moon, { className: "h-4 w-4" }) }) }), jsxRuntime.jsx(TooltipContent, { children: isDarkMode ? 'Light Mode' : 'Dark Mode' })] })] })] }));
|
|
28456
28685
|
}
|
|
28457
28686
|
|
|
28458
28687
|
const iconMap = {
|