form-builder-pro 1.0.0 → 1.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.mjs CHANGED
@@ -4353,6 +4353,29 @@ var formStore = createStore((set, get) => ({
4353
4353
  historyIndex: historyIndex + 1
4354
4354
  });
4355
4355
  },
4356
+ addTemplateFields: (targetSectionId, template, index2) => {
4357
+ set((state) => {
4358
+ const sectionIndex = state.schema.sections.findIndex((s) => s.id === targetSectionId);
4359
+ if (sectionIndex === -1)
4360
+ return state;
4361
+ const section = state.schema.sections[sectionIndex];
4362
+ const newFields = template.fields.map(cloneField);
4363
+ const currentFields = [...section.fields];
4364
+ if (typeof index2 === "number" && index2 >= 0) {
4365
+ currentFields.splice(index2, 0, ...newFields);
4366
+ } else {
4367
+ currentFields.push(...newFields);
4368
+ }
4369
+ const newSection = { ...section, fields: currentFields };
4370
+ const newSections = [...state.schema.sections];
4371
+ newSections[sectionIndex] = newSection;
4372
+ return {
4373
+ schema: { ...state.schema, sections: newSections },
4374
+ history: [...state.history.slice(0, state.historyIndex + 1), { ...state.schema, sections: newSections }],
4375
+ historyIndex: state.historyIndex + 1
4376
+ };
4377
+ });
4378
+ },
4356
4379
  undo: () => {
4357
4380
  const { history, historyIndex } = get();
4358
4381
  if (historyIndex > 0) {
@@ -4476,7 +4499,7 @@ var FieldRenderer = class {
4476
4499
  const wrapper = createElement("div", { className: "w-full" });
4477
4500
  if (field.type !== "checkbox") {
4478
4501
  const label = createElement("label", {
4479
- className: "text-sm font-medium leading-none mb-2 block text-gray-900 dark:text-gray-100",
4502
+ className: "text-xs sm:text-sm font-medium leading-none mb-2 block text-gray-900 dark:text-gray-100",
4480
4503
  text: field.label
4481
4504
  });
4482
4505
  if (field.required) {
@@ -4485,7 +4508,7 @@ var FieldRenderer = class {
4485
4508
  wrapper.appendChild(label);
4486
4509
  } else {
4487
4510
  const label = createElement("label", {
4488
- className: "text-sm font-medium leading-none mb-2 block text-gray-900 dark:text-gray-100",
4511
+ className: "text-xs sm:text-sm font-medium leading-none mb-2 block text-gray-900 dark:text-gray-100",
4489
4512
  text: field.label
4490
4513
  });
4491
4514
  if (field.required) {
@@ -4497,7 +4520,7 @@ var FieldRenderer = class {
4497
4520
  switch (field.type) {
4498
4521
  case "textarea":
4499
4522
  input = createElement("textarea", {
4500
- className: "flex min-h-[80px] w-full rounded-md border border-input bg-background px-3 py-2 text-sm ring-offset-background placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50",
4523
+ className: "flex min-h-[80px] w-full rounded-md border border-input bg-background px-3 py-2 text-sm sm:text-base ring-offset-background placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50",
4501
4524
  placeholder: field.placeholder,
4502
4525
  value: value || "",
4503
4526
  disabled: readOnly,
@@ -4506,7 +4529,7 @@ var FieldRenderer = class {
4506
4529
  break;
4507
4530
  case "select":
4508
4531
  input = createElement("select", {
4509
- className: "flex h-10 w-full rounded-md border border-input bg-background px-3 py-2 text-sm ring-offset-background focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50",
4532
+ className: "flex min-h-touch w-full rounded-md border border-input bg-background px-3 py-2 text-sm sm:text-base ring-offset-background focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50",
4510
4533
  value: value || "",
4511
4534
  disabled: readOnly,
4512
4535
  onchange: (e) => onChange?.(e.target.value)
@@ -4517,10 +4540,10 @@ var FieldRenderer = class {
4517
4540
  });
4518
4541
  break;
4519
4542
  case "checkbox":
4520
- input = createElement("div", { className: "flex items-center h-10" });
4543
+ input = createElement("div", { className: "flex items-center min-h-touch" });
4521
4544
  const checkbox = createElement("input", {
4522
4545
  type: "checkbox",
4523
- className: "h-5 w-5 rounded border-gray-300 text-primary focus:ring-primary cursor-pointer",
4546
+ className: "h-5 w-5 sm:h-6 sm:w-6 rounded border-gray-300 text-primary focus:ring-primary cursor-pointer",
4524
4547
  checked: !!value,
4525
4548
  disabled: readOnly,
4526
4549
  onchange: (e) => onChange?.(e.target.checked)
@@ -4530,18 +4553,18 @@ var FieldRenderer = class {
4530
4553
  case "radio":
4531
4554
  input = createElement("div", { className: "space-y-2" });
4532
4555
  field.options?.forEach((opt) => {
4533
- const radioWrapper = createElement("div", { className: "flex items-center space-x-2" });
4556
+ const radioWrapper = createElement("div", { className: "flex items-center space-x-2 min-h-touch" });
4534
4557
  const radio = createElement("input", {
4535
4558
  type: "radio",
4536
4559
  name: field.id,
4537
4560
  value: opt.value,
4538
4561
  checked: value === opt.value,
4539
4562
  disabled: readOnly,
4540
- className: "aspect-square h-4 w-4 rounded-full border border-primary text-primary ring-offset-background focus:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50",
4563
+ className: "aspect-square h-4 w-4 sm:h-5 sm:w-5 rounded-full border border-primary text-primary ring-offset-background focus:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50",
4541
4564
  onchange: (e) => onChange?.(e.target.value)
4542
4565
  });
4543
4566
  const radioLabel = createElement("label", {
4544
- className: "text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70",
4567
+ className: "text-xs sm:text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70",
4545
4568
  text: opt.label
4546
4569
  });
4547
4570
  radioWrapper.appendChild(radio);
@@ -4552,7 +4575,7 @@ var FieldRenderer = class {
4552
4575
  default:
4553
4576
  input = createElement("input", {
4554
4577
  type: field.type === "phone" ? "tel" : field.type,
4555
- className: "flex h-10 w-full rounded-md border border-input bg-background px-3 py-2 text-sm ring-offset-background file:border-0 file:bg-transparent file:text-sm file:font-medium placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50",
4578
+ className: "flex min-h-touch w-full rounded-md border border-input bg-background px-3 py-2 text-sm sm:text-base ring-offset-background file:border-0 file:bg-transparent file:text-sm file:font-medium placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50",
4556
4579
  placeholder: field.placeholder,
4557
4580
  value: value || "",
4558
4581
  disabled: readOnly,
@@ -4561,7 +4584,7 @@ var FieldRenderer = class {
4561
4584
  }
4562
4585
  wrapper.appendChild(input);
4563
4586
  if (field.description) {
4564
- wrapper.appendChild(createElement("p", { className: "text-sm text-muted-foreground mt-1", text: field.description }));
4587
+ wrapper.appendChild(createElement("p", { className: "text-xs sm:text-sm text-muted-foreground mt-1", text: field.description }));
4565
4588
  }
4566
4589
  return wrapper;
4567
4590
  }
@@ -4585,11 +4608,11 @@ var FormRenderer = class {
4585
4608
  }
4586
4609
  render() {
4587
4610
  this.container.innerHTML = "";
4588
- const form = createElement("form", { className: "space-y-8" });
4589
- form.appendChild(createElement("h1", { className: "text-2xl font-bold text-gray-900 dark:text-white", text: this.schema.title }));
4611
+ const form = createElement("form", { className: "space-y-6 md:space-y-8" });
4612
+ form.appendChild(createElement("h1", { className: "text-xl md:text-2xl font-bold text-gray-900 dark:text-white", text: this.schema.title }));
4590
4613
  this.schema.sections.forEach((section) => {
4591
- const sectionEl = createElement("div", { className: "space-y-4" });
4592
- sectionEl.appendChild(createElement("h2", { className: "text-xl font-semibold text-gray-800 dark:text-gray-200 border-b pb-2", text: section.title }));
4614
+ const sectionEl = createElement("div", { className: "space-y-3 md:space-y-4" });
4615
+ sectionEl.appendChild(createElement("h2", { className: "text-lg md:text-xl font-semibold text-gray-800 dark:text-gray-200 border-b pb-2", text: section.title }));
4593
4616
  const grid = createElement("div", { className: "form-builder-grid" });
4594
4617
  section.fields.forEach((field) => {
4595
4618
  const fieldWrapper = createElement("div");
@@ -4616,14 +4639,14 @@ var FormRenderer = class {
4616
4639
  });
4617
4640
  const submitBtn = createElement("button", {
4618
4641
  type: "submit",
4619
- className: "px-6 py-2 bg-blue-600 text-white font-medium rounded-md hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-blue-500 focus:ring-offset-2 transition-colors",
4642
+ className: "w-full sm:w-auto px-6 py-3 min-h-touch bg-blue-600 text-white font-medium rounded-md hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-blue-500 focus:ring-offset-2 transition-colors",
4620
4643
  text: "Submit"
4621
4644
  });
4622
4645
  form.onsubmit = (e) => {
4623
4646
  e.preventDefault();
4624
4647
  this.onSubmit?.(this.data);
4625
4648
  };
4626
- const btnWrapper = createElement("div", { className: "pt-4" });
4649
+ const btnWrapper = createElement("div", { className: "pt-4 flex justify-center sm:justify-start" });
4627
4650
  btnWrapper.appendChild(submitBtn);
4628
4651
  form.appendChild(btnWrapper);
4629
4652
  this.container.appendChild(form);
@@ -6982,7 +7005,7 @@ var FormBuilder = class {
6982
7005
  this.container.innerHTML = "";
6983
7006
  const wrapper = createElement("div", { className: "flex flex-col h-screen " });
6984
7007
  wrapper.appendChild(this.renderToolbar(state));
6985
- const main = createElement("div", { className: "flex flex-1 overflow-hidden" });
7008
+ const main = createElement("div", { className: "flex flex-col md:flex-row flex-1 overflow-hidden" });
6986
7009
  if (state.isPreviewMode) {
6987
7010
  const previewContainer = createElement("div", { className: "flex-1 p-8 overflow-y-auto bg-white dark:bg-gray-900 flex justify-center" });
6988
7011
  const inner = createElement("div", { className: "w-full max-w-3xl" });
@@ -6990,9 +7013,15 @@ var FormBuilder = class {
6990
7013
  previewContainer.appendChild(inner);
6991
7014
  main.appendChild(previewContainer);
6992
7015
  } else {
6993
- main.appendChild(this.renderToolbox());
6994
- main.appendChild(this.renderCanvas(state));
6995
- main.appendChild(this.renderConfigPanel(state));
7016
+ const toolboxWrapper = createElement("div", { className: "form-builder-toolbox-wrapper w-full md:w-80 bg-white dark:bg-gray-900 border-r md:border-r border-b md:border-b-0 border-gray-200 dark:border-gray-800" });
7017
+ toolboxWrapper.appendChild(this.renderToolbox());
7018
+ main.appendChild(toolboxWrapper);
7019
+ const canvasWrapper = createElement("div", { className: "form-builder-canvas flex-1 overflow-y-auto" });
7020
+ canvasWrapper.appendChild(this.renderCanvas(state));
7021
+ main.appendChild(canvasWrapper);
7022
+ const configWrapper = createElement("div", { className: "form-builder-config-wrapper w-full md:w-80 bg-white dark:bg-gray-900 border-l md:border-l border-t md:border-t-0 border-gray-200 dark:border-gray-800" });
7023
+ configWrapper.appendChild(this.renderConfigPanel(state));
7024
+ main.appendChild(configWrapper);
6996
7025
  }
6997
7026
  wrapper.appendChild(main);
6998
7027
  this.container.appendChild(wrapper);
@@ -7090,7 +7119,7 @@ var FormBuilder = class {
7090
7119
  return toolbar;
7091
7120
  }
7092
7121
  renderToolbox() {
7093
- const toolbox = createElement("div", { className: "w-80 bg-white dark:bg-gray-900 border-r border-gray-200 dark:border-gray-800 flex flex-col h-full" });
7122
+ const toolbox = createElement("div", { className: "bg-white dark:bg-gray-900 flex flex-col h-full" });
7094
7123
  const tabs = createElement("div", { className: "flex border-b border-gray-200 dark:border-gray-800" });
7095
7124
  const createTab = (id, label) => {
7096
7125
  const isActive = this.activeTab === id;
@@ -7189,7 +7218,7 @@ var FormBuilder = class {
7189
7218
  }
7190
7219
  renderCanvas(state) {
7191
7220
  const canvas = createElement("div", {
7192
- className: "flex-1 bg-white dark:bg-gray-950 p-8 overflow-y-auto h-full",
7221
+ className: "flex-1 bg-white dark:bg-gray-950 p-4 md:p-8 overflow-y-auto",
7193
7222
  onclick: (e) => {
7194
7223
  if (e.target === canvas || e.target === canvas.firstElementChild) {
7195
7224
  formStore.getState().selectField(null);
@@ -7306,7 +7335,7 @@ var FormBuilder = class {
7306
7335
  return canvas;
7307
7336
  }
7308
7337
  renderConfigPanel(state) {
7309
- const panel = createElement("div", { className: "w-80 bg-white dark:bg-gray-900 border-l border-gray-200 dark:border-gray-800 flex flex-col h-full" });
7338
+ const panel = createElement("div", { className: "bg-white dark:bg-gray-900 flex flex-col h-full" });
7310
7339
  const selectedField = state.schema.sections.flatMap((s) => s.fields).find((f) => f.id === state.selectedFieldId);
7311
7340
  if (!selectedField) {
7312
7341
  panel.appendChild(createElement("div", { className: "p-6 text-center text-gray-500", text: "Select a field to configure" }));
@@ -7552,6 +7581,16 @@ var FormBuilder = class {
7552
7581
  const type = item.getAttribute("data-type");
7553
7582
  const sectionId = list.getAttribute("data-section-id");
7554
7583
  if (type && sectionId) {
7584
+ if (type === "template-section") {
7585
+ const templateId = item.getAttribute("data-template-id");
7586
+ const templates = formStore.getState().templates;
7587
+ const template = templates.find((t) => t.id === templateId);
7588
+ item.remove();
7589
+ if (template) {
7590
+ formStore.getState().addTemplateFields(sectionId, template, evt.newIndex);
7591
+ }
7592
+ return;
7593
+ }
7555
7594
  item.remove();
7556
7595
  formStore.getState().addField(sectionId, type, evt.newIndex);
7557
7596
  } else if (sectionId) {