@thanh01.pmt/interactive-quiz-kit 1.0.68 → 1.0.69

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.
@@ -76443,8 +76443,8 @@ function MetadataImportControls({ metadataName, onImport }) {
76443
76443
  const handleFileSelected = (event) => {
76444
76444
  const file = event.target.files?.[0];
76445
76445
  if (!file) return;
76446
- if (file.type !== "application/json" && !file.name.endsWith(".csv")) {
76447
- toast2({ title: "Invalid File Type", description: "Please select a JSON or CSV file.", variant: "destructive" });
76446
+ if (!file.type.includes("json") && !file.type.includes("tab-separated-values") && !file.name.endsWith(".tsv") && !file.name.endsWith(".txt")) {
76447
+ toast2({ title: "Invalid File Type", description: "Please select a JSON or TSV/TXT file.", variant: "destructive" });
76448
76448
  if (event.target) event.target.value = "";
76449
76449
  return;
76450
76450
  }
@@ -76452,18 +76452,18 @@ function MetadataImportControls({ metadataName, onImport }) {
76452
76452
  try {
76453
76453
  const fileContent = await file.text();
76454
76454
  let records = [];
76455
- if (file.type === "application/json") {
76455
+ if (file.type.includes("json")) {
76456
76456
  records = JSON.parse(fileContent);
76457
76457
  if (!Array.isArray(records)) throw new Error("JSON file must contain an array of objects.");
76458
- } else if (file.name.endsWith(".csv")) {
76459
- const lines = fileContent.split(/\r\n|\n/).filter((line) => line.trim() !== "");
76460
- if (lines.length < 2) throw new Error("CSV must have a header and at least one data row.");
76461
- const headers = lines[0].split(",").map((h2) => h2.trim());
76458
+ } else {
76459
+ const lines = fileContent.split(/\r?\n/).filter((line) => line.trim() !== "");
76460
+ if (lines.length < 2) throw new Error("TSV file must have a header and at least one data row.");
76461
+ const headers = lines[0].split(" ").map((h2) => h2.trim());
76462
76462
  records = lines.slice(1).map((line) => {
76463
- const values = line.split(",").map((v) => v.trim());
76463
+ const values = line.split(" ");
76464
76464
  const record = {};
76465
76465
  headers.forEach((header, index3) => {
76466
- record[header] = values[index3];
76466
+ record[header] = values[index3]?.trim() || "";
76467
76467
  });
76468
76468
  return record;
76469
76469
  });
@@ -76490,7 +76490,7 @@ function MetadataImportControls({ metadataName, onImport }) {
76490
76490
  }
76491
76491
  });
76492
76492
  };
76493
- return /* @__PURE__ */ React119__namespace.default.createElement(Dialog2, { open: isOpen, onOpenChange: setIsOpen }, /* @__PURE__ */ React119__namespace.default.createElement(DialogTrigger2, { asChild: true }, /* @__PURE__ */ React119__namespace.default.createElement(Button, { size: "sm", variant: "outline" }, /* @__PURE__ */ React119__namespace.default.createElement(Upload, { className: "mr-2 h-4 w-4" }), " Import ", metadataName)), /* @__PURE__ */ React119__namespace.default.createElement(DialogContent2, null, /* @__PURE__ */ React119__namespace.default.createElement(DialogHeader, null, /* @__PURE__ */ React119__namespace.default.createElement(DialogTitle2, null, "Bulk Import ", metadataName), /* @__PURE__ */ React119__namespace.default.createElement(DialogDescription2, null, "Import multiple records from a file or by pasting JSON data.")), /* @__PURE__ */ React119__namespace.default.createElement(Tabs2, { defaultValue: "file" }, /* @__PURE__ */ React119__namespace.default.createElement(TabsList2, { className: "grid w-full grid-cols-2" }, /* @__PURE__ */ React119__namespace.default.createElement(TabsTrigger2, { value: "file" }, /* @__PURE__ */ React119__namespace.default.createElement(FileJson, { className: "mr-2 h-4 w-4" }), " From File"), /* @__PURE__ */ React119__namespace.default.createElement(TabsTrigger2, { value: "text" }, /* @__PURE__ */ React119__namespace.default.createElement(ClipboardPaste, { className: "mr-2 h-4 w-4" }), " From Text")), /* @__PURE__ */ React119__namespace.default.createElement(TabsContent2, { value: "file", className: "pt-4" }, /* @__PURE__ */ React119__namespace.default.createElement("div", { className: "space-y-3" }, /* @__PURE__ */ React119__namespace.default.createElement("p", { className: "text-sm text-muted-foreground" }, "Select a JSON or CSV file. Ensure column names in the file match the table schema (e.g., 'code', 'name', 'subject_code')."), /* @__PURE__ */ React119__namespace.default.createElement(Button, { variant: "outline", onClick: () => fileInputRef.current?.click(), disabled: isImporting }, isImporting ? /* @__PURE__ */ React119__namespace.default.createElement(LoaderCircle, { className: "mr-2 h-4 w-4 animate-spin" }) : /* @__PURE__ */ React119__namespace.default.createElement(Upload, { className: "mr-2 h-4 w-4" }), isImporting ? "Importing..." : "Select File"), /* @__PURE__ */ React119__namespace.default.createElement("input", { type: "file", ref: fileInputRef, onChange: handleFileSelected, accept: ".json,.csv", className: "hidden" }))), /* @__PURE__ */ React119__namespace.default.createElement(TabsContent2, { value: "text", className: "pt-4" }, /* @__PURE__ */ React119__namespace.default.createElement("div", { className: "space-y-3" }, /* @__PURE__ */ React119__namespace.default.createElement(Label2, { htmlFor: "jsonInput" }, "JSON Data (Array of Objects)"), /* @__PURE__ */ React119__namespace.default.createElement(
76493
+ return /* @__PURE__ */ React119__namespace.default.createElement(Dialog2, { open: isOpen, onOpenChange: setIsOpen }, /* @__PURE__ */ React119__namespace.default.createElement(DialogTrigger2, { asChild: true }, /* @__PURE__ */ React119__namespace.default.createElement(Button, { size: "sm", variant: "outline" }, /* @__PURE__ */ React119__namespace.default.createElement(Upload, { className: "mr-2 h-4 w-4" }), " Import ", metadataName)), /* @__PURE__ */ React119__namespace.default.createElement(DialogContent2, null, /* @__PURE__ */ React119__namespace.default.createElement(DialogHeader, null, /* @__PURE__ */ React119__namespace.default.createElement(DialogTitle2, null, "Bulk Import ", metadataName), /* @__PURE__ */ React119__namespace.default.createElement(DialogDescription2, null, "Import multiple records from a file or by pasting JSON data.")), /* @__PURE__ */ React119__namespace.default.createElement(Tabs2, { defaultValue: "file" }, /* @__PURE__ */ React119__namespace.default.createElement(TabsList2, { className: "grid w-full grid-cols-2" }, /* @__PURE__ */ React119__namespace.default.createElement(TabsTrigger2, { value: "file" }, /* @__PURE__ */ React119__namespace.default.createElement(FileJson, { className: "mr-2 h-4 w-4" }), " From File"), /* @__PURE__ */ React119__namespace.default.createElement(TabsTrigger2, { value: "text" }, /* @__PURE__ */ React119__namespace.default.createElement(ClipboardPaste, { className: "mr-2 h-4 w-4" }), " From Text")), /* @__PURE__ */ React119__namespace.default.createElement(TabsContent2, { value: "file", className: "pt-4" }, /* @__PURE__ */ React119__namespace.default.createElement("div", { className: "space-y-3" }, /* @__PURE__ */ React119__namespace.default.createElement("p", { className: "text-sm text-muted-foreground" }, "Select a JSON or TSV/TXT file. Ensure column names in the file match the table schema (e.g., 'code', 'name', 'subjectCode')."), /* @__PURE__ */ React119__namespace.default.createElement(Button, { variant: "outline", onClick: () => fileInputRef.current?.click(), disabled: isImporting }, isImporting ? /* @__PURE__ */ React119__namespace.default.createElement(LoaderCircle, { className: "mr-2 h-4 w-4 animate-spin" }) : /* @__PURE__ */ React119__namespace.default.createElement(Upload, { className: "mr-2 h-4 w-4" }), isImporting ? "Importing..." : "Select File"), /* @__PURE__ */ React119__namespace.default.createElement("input", { type: "file", ref: fileInputRef, onChange: handleFileSelected, accept: ".json,.tsv,.txt,text/tab-separated-values", className: "hidden" }))), /* @__PURE__ */ React119__namespace.default.createElement(TabsContent2, { value: "text", className: "pt-4" }, /* @__PURE__ */ React119__namespace.default.createElement("div", { className: "space-y-3" }, /* @__PURE__ */ React119__namespace.default.createElement(Label2, { htmlFor: "jsonInput" }, "JSON Data (Array of Objects)"), /* @__PURE__ */ React119__namespace.default.createElement(
76494
76494
  Textarea,
76495
76495
  {
76496
76496
  id: "jsonInput",
@@ -76378,8 +76378,8 @@ function MetadataImportControls({ metadataName, onImport }) {
76378
76378
  const handleFileSelected = (event) => {
76379
76379
  const file = event.target.files?.[0];
76380
76380
  if (!file) return;
76381
- if (file.type !== "application/json" && !file.name.endsWith(".csv")) {
76382
- toast2({ title: "Invalid File Type", description: "Please select a JSON or CSV file.", variant: "destructive" });
76381
+ if (!file.type.includes("json") && !file.type.includes("tab-separated-values") && !file.name.endsWith(".tsv") && !file.name.endsWith(".txt")) {
76382
+ toast2({ title: "Invalid File Type", description: "Please select a JSON or TSV/TXT file.", variant: "destructive" });
76383
76383
  if (event.target) event.target.value = "";
76384
76384
  return;
76385
76385
  }
@@ -76387,18 +76387,18 @@ function MetadataImportControls({ metadataName, onImport }) {
76387
76387
  try {
76388
76388
  const fileContent = await file.text();
76389
76389
  let records = [];
76390
- if (file.type === "application/json") {
76390
+ if (file.type.includes("json")) {
76391
76391
  records = JSON.parse(fileContent);
76392
76392
  if (!Array.isArray(records)) throw new Error("JSON file must contain an array of objects.");
76393
- } else if (file.name.endsWith(".csv")) {
76394
- const lines = fileContent.split(/\r\n|\n/).filter((line) => line.trim() !== "");
76395
- if (lines.length < 2) throw new Error("CSV must have a header and at least one data row.");
76396
- const headers = lines[0].split(",").map((h2) => h2.trim());
76393
+ } else {
76394
+ const lines = fileContent.split(/\r?\n/).filter((line) => line.trim() !== "");
76395
+ if (lines.length < 2) throw new Error("TSV file must have a header and at least one data row.");
76396
+ const headers = lines[0].split(" ").map((h2) => h2.trim());
76397
76397
  records = lines.slice(1).map((line) => {
76398
- const values = line.split(",").map((v) => v.trim());
76398
+ const values = line.split(" ");
76399
76399
  const record = {};
76400
76400
  headers.forEach((header, index3) => {
76401
- record[header] = values[index3];
76401
+ record[header] = values[index3]?.trim() || "";
76402
76402
  });
76403
76403
  return record;
76404
76404
  });
@@ -76425,7 +76425,7 @@ function MetadataImportControls({ metadataName, onImport }) {
76425
76425
  }
76426
76426
  });
76427
76427
  };
76428
- return /* @__PURE__ */ React119__default.createElement(Dialog2, { open: isOpen, onOpenChange: setIsOpen }, /* @__PURE__ */ React119__default.createElement(DialogTrigger2, { asChild: true }, /* @__PURE__ */ React119__default.createElement(Button, { size: "sm", variant: "outline" }, /* @__PURE__ */ React119__default.createElement(Upload, { className: "mr-2 h-4 w-4" }), " Import ", metadataName)), /* @__PURE__ */ React119__default.createElement(DialogContent2, null, /* @__PURE__ */ React119__default.createElement(DialogHeader, null, /* @__PURE__ */ React119__default.createElement(DialogTitle2, null, "Bulk Import ", metadataName), /* @__PURE__ */ React119__default.createElement(DialogDescription2, null, "Import multiple records from a file or by pasting JSON data.")), /* @__PURE__ */ React119__default.createElement(Tabs2, { defaultValue: "file" }, /* @__PURE__ */ React119__default.createElement(TabsList2, { className: "grid w-full grid-cols-2" }, /* @__PURE__ */ React119__default.createElement(TabsTrigger2, { value: "file" }, /* @__PURE__ */ React119__default.createElement(FileJson, { className: "mr-2 h-4 w-4" }), " From File"), /* @__PURE__ */ React119__default.createElement(TabsTrigger2, { value: "text" }, /* @__PURE__ */ React119__default.createElement(ClipboardPaste, { className: "mr-2 h-4 w-4" }), " From Text")), /* @__PURE__ */ React119__default.createElement(TabsContent2, { value: "file", className: "pt-4" }, /* @__PURE__ */ React119__default.createElement("div", { className: "space-y-3" }, /* @__PURE__ */ React119__default.createElement("p", { className: "text-sm text-muted-foreground" }, "Select a JSON or CSV file. Ensure column names in the file match the table schema (e.g., 'code', 'name', 'subject_code')."), /* @__PURE__ */ React119__default.createElement(Button, { variant: "outline", onClick: () => fileInputRef.current?.click(), disabled: isImporting }, isImporting ? /* @__PURE__ */ React119__default.createElement(LoaderCircle, { className: "mr-2 h-4 w-4 animate-spin" }) : /* @__PURE__ */ React119__default.createElement(Upload, { className: "mr-2 h-4 w-4" }), isImporting ? "Importing..." : "Select File"), /* @__PURE__ */ React119__default.createElement("input", { type: "file", ref: fileInputRef, onChange: handleFileSelected, accept: ".json,.csv", className: "hidden" }))), /* @__PURE__ */ React119__default.createElement(TabsContent2, { value: "text", className: "pt-4" }, /* @__PURE__ */ React119__default.createElement("div", { className: "space-y-3" }, /* @__PURE__ */ React119__default.createElement(Label2, { htmlFor: "jsonInput" }, "JSON Data (Array of Objects)"), /* @__PURE__ */ React119__default.createElement(
76428
+ return /* @__PURE__ */ React119__default.createElement(Dialog2, { open: isOpen, onOpenChange: setIsOpen }, /* @__PURE__ */ React119__default.createElement(DialogTrigger2, { asChild: true }, /* @__PURE__ */ React119__default.createElement(Button, { size: "sm", variant: "outline" }, /* @__PURE__ */ React119__default.createElement(Upload, { className: "mr-2 h-4 w-4" }), " Import ", metadataName)), /* @__PURE__ */ React119__default.createElement(DialogContent2, null, /* @__PURE__ */ React119__default.createElement(DialogHeader, null, /* @__PURE__ */ React119__default.createElement(DialogTitle2, null, "Bulk Import ", metadataName), /* @__PURE__ */ React119__default.createElement(DialogDescription2, null, "Import multiple records from a file or by pasting JSON data.")), /* @__PURE__ */ React119__default.createElement(Tabs2, { defaultValue: "file" }, /* @__PURE__ */ React119__default.createElement(TabsList2, { className: "grid w-full grid-cols-2" }, /* @__PURE__ */ React119__default.createElement(TabsTrigger2, { value: "file" }, /* @__PURE__ */ React119__default.createElement(FileJson, { className: "mr-2 h-4 w-4" }), " From File"), /* @__PURE__ */ React119__default.createElement(TabsTrigger2, { value: "text" }, /* @__PURE__ */ React119__default.createElement(ClipboardPaste, { className: "mr-2 h-4 w-4" }), " From Text")), /* @__PURE__ */ React119__default.createElement(TabsContent2, { value: "file", className: "pt-4" }, /* @__PURE__ */ React119__default.createElement("div", { className: "space-y-3" }, /* @__PURE__ */ React119__default.createElement("p", { className: "text-sm text-muted-foreground" }, "Select a JSON or TSV/TXT file. Ensure column names in the file match the table schema (e.g., 'code', 'name', 'subjectCode')."), /* @__PURE__ */ React119__default.createElement(Button, { variant: "outline", onClick: () => fileInputRef.current?.click(), disabled: isImporting }, isImporting ? /* @__PURE__ */ React119__default.createElement(LoaderCircle, { className: "mr-2 h-4 w-4 animate-spin" }) : /* @__PURE__ */ React119__default.createElement(Upload, { className: "mr-2 h-4 w-4" }), isImporting ? "Importing..." : "Select File"), /* @__PURE__ */ React119__default.createElement("input", { type: "file", ref: fileInputRef, onChange: handleFileSelected, accept: ".json,.tsv,.txt,text/tab-separated-values", className: "hidden" }))), /* @__PURE__ */ React119__default.createElement(TabsContent2, { value: "text", className: "pt-4" }, /* @__PURE__ */ React119__default.createElement("div", { className: "space-y-3" }, /* @__PURE__ */ React119__default.createElement(Label2, { htmlFor: "jsonInput" }, "JSON Data (Array of Objects)"), /* @__PURE__ */ React119__default.createElement(
76429
76429
  Textarea,
76430
76430
  {
76431
76431
  id: "jsonInput",
package/dist/react-ui.cjs CHANGED
@@ -138739,8 +138739,8 @@ function MetadataImportControls({ metadataName, onImport }) {
138739
138739
  const handleFileSelected = (event) => {
138740
138740
  const file = event.target.files?.[0];
138741
138741
  if (!file) return;
138742
- if (file.type !== "application/json" && !file.name.endsWith(".csv")) {
138743
- toast2({ title: "Invalid File Type", description: "Please select a JSON or CSV file.", variant: "destructive" });
138742
+ if (!file.type.includes("json") && !file.type.includes("tab-separated-values") && !file.name.endsWith(".tsv") && !file.name.endsWith(".txt")) {
138743
+ toast2({ title: "Invalid File Type", description: "Please select a JSON or TSV/TXT file.", variant: "destructive" });
138744
138744
  if (event.target) event.target.value = "";
138745
138745
  return;
138746
138746
  }
@@ -138748,18 +138748,18 @@ function MetadataImportControls({ metadataName, onImport }) {
138748
138748
  try {
138749
138749
  const fileContent = await file.text();
138750
138750
  let records = [];
138751
- if (file.type === "application/json") {
138751
+ if (file.type.includes("json")) {
138752
138752
  records = JSON.parse(fileContent);
138753
138753
  if (!Array.isArray(records)) throw new Error("JSON file must contain an array of objects.");
138754
- } else if (file.name.endsWith(".csv")) {
138755
- const lines = fileContent.split(/\r\n|\n/).filter((line) => line.trim() !== "");
138756
- if (lines.length < 2) throw new Error("CSV must have a header and at least one data row.");
138757
- const headers = lines[0].split(",").map((h3) => h3.trim());
138754
+ } else {
138755
+ const lines = fileContent.split(/\r?\n/).filter((line) => line.trim() !== "");
138756
+ if (lines.length < 2) throw new Error("TSV file must have a header and at least one data row.");
138757
+ const headers = lines[0].split(" ").map((h3) => h3.trim());
138758
138758
  records = lines.slice(1).map((line) => {
138759
- const values = line.split(",").map((v) => v.trim());
138759
+ const values = line.split(" ");
138760
138760
  const record = {};
138761
138761
  headers.forEach((header, index3) => {
138762
- record[header] = values[index3];
138762
+ record[header] = values[index3]?.trim() || "";
138763
138763
  });
138764
138764
  return record;
138765
138765
  });
@@ -138786,7 +138786,7 @@ function MetadataImportControls({ metadataName, onImport }) {
138786
138786
  }
138787
138787
  });
138788
138788
  };
138789
- return /* @__PURE__ */ React169__namespace.default.createElement(Dialog2, { open: isOpen, onOpenChange: setIsOpen }, /* @__PURE__ */ React169__namespace.default.createElement(DialogTrigger2, { asChild: true }, /* @__PURE__ */ React169__namespace.default.createElement(Button, { size: "sm", variant: "outline" }, /* @__PURE__ */ React169__namespace.default.createElement(Upload, { className: "mr-2 h-4 w-4" }), " Import ", metadataName)), /* @__PURE__ */ React169__namespace.default.createElement(DialogContent2, null, /* @__PURE__ */ React169__namespace.default.createElement(DialogHeader, null, /* @__PURE__ */ React169__namespace.default.createElement(DialogTitle2, null, "Bulk Import ", metadataName), /* @__PURE__ */ React169__namespace.default.createElement(DialogDescription2, null, "Import multiple records from a file or by pasting JSON data.")), /* @__PURE__ */ React169__namespace.default.createElement(Tabs2, { defaultValue: "file" }, /* @__PURE__ */ React169__namespace.default.createElement(TabsList2, { className: "grid w-full grid-cols-2" }, /* @__PURE__ */ React169__namespace.default.createElement(TabsTrigger2, { value: "file" }, /* @__PURE__ */ React169__namespace.default.createElement(FileJson, { className: "mr-2 h-4 w-4" }), " From File"), /* @__PURE__ */ React169__namespace.default.createElement(TabsTrigger2, { value: "text" }, /* @__PURE__ */ React169__namespace.default.createElement(ClipboardPaste, { className: "mr-2 h-4 w-4" }), " From Text")), /* @__PURE__ */ React169__namespace.default.createElement(TabsContent2, { value: "file", className: "pt-4" }, /* @__PURE__ */ React169__namespace.default.createElement("div", { className: "space-y-3" }, /* @__PURE__ */ React169__namespace.default.createElement("p", { className: "text-sm text-muted-foreground" }, "Select a JSON or CSV file. Ensure column names in the file match the table schema (e.g., 'code', 'name', 'subject_code')."), /* @__PURE__ */ React169__namespace.default.createElement(Button, { variant: "outline", onClick: () => fileInputRef.current?.click(), disabled: isImporting }, isImporting ? /* @__PURE__ */ React169__namespace.default.createElement(LoaderCircle, { className: "mr-2 h-4 w-4 animate-spin" }) : /* @__PURE__ */ React169__namespace.default.createElement(Upload, { className: "mr-2 h-4 w-4" }), isImporting ? "Importing..." : "Select File"), /* @__PURE__ */ React169__namespace.default.createElement("input", { type: "file", ref: fileInputRef, onChange: handleFileSelected, accept: ".json,.csv", className: "hidden" }))), /* @__PURE__ */ React169__namespace.default.createElement(TabsContent2, { value: "text", className: "pt-4" }, /* @__PURE__ */ React169__namespace.default.createElement("div", { className: "space-y-3" }, /* @__PURE__ */ React169__namespace.default.createElement(Label2, { htmlFor: "jsonInput" }, "JSON Data (Array of Objects)"), /* @__PURE__ */ React169__namespace.default.createElement(
138789
+ return /* @__PURE__ */ React169__namespace.default.createElement(Dialog2, { open: isOpen, onOpenChange: setIsOpen }, /* @__PURE__ */ React169__namespace.default.createElement(DialogTrigger2, { asChild: true }, /* @__PURE__ */ React169__namespace.default.createElement(Button, { size: "sm", variant: "outline" }, /* @__PURE__ */ React169__namespace.default.createElement(Upload, { className: "mr-2 h-4 w-4" }), " Import ", metadataName)), /* @__PURE__ */ React169__namespace.default.createElement(DialogContent2, null, /* @__PURE__ */ React169__namespace.default.createElement(DialogHeader, null, /* @__PURE__ */ React169__namespace.default.createElement(DialogTitle2, null, "Bulk Import ", metadataName), /* @__PURE__ */ React169__namespace.default.createElement(DialogDescription2, null, "Import multiple records from a file or by pasting JSON data.")), /* @__PURE__ */ React169__namespace.default.createElement(Tabs2, { defaultValue: "file" }, /* @__PURE__ */ React169__namespace.default.createElement(TabsList2, { className: "grid w-full grid-cols-2" }, /* @__PURE__ */ React169__namespace.default.createElement(TabsTrigger2, { value: "file" }, /* @__PURE__ */ React169__namespace.default.createElement(FileJson, { className: "mr-2 h-4 w-4" }), " From File"), /* @__PURE__ */ React169__namespace.default.createElement(TabsTrigger2, { value: "text" }, /* @__PURE__ */ React169__namespace.default.createElement(ClipboardPaste, { className: "mr-2 h-4 w-4" }), " From Text")), /* @__PURE__ */ React169__namespace.default.createElement(TabsContent2, { value: "file", className: "pt-4" }, /* @__PURE__ */ React169__namespace.default.createElement("div", { className: "space-y-3" }, /* @__PURE__ */ React169__namespace.default.createElement("p", { className: "text-sm text-muted-foreground" }, "Select a JSON or TSV/TXT file. Ensure column names in the file match the table schema (e.g., 'code', 'name', 'subjectCode')."), /* @__PURE__ */ React169__namespace.default.createElement(Button, { variant: "outline", onClick: () => fileInputRef.current?.click(), disabled: isImporting }, isImporting ? /* @__PURE__ */ React169__namespace.default.createElement(LoaderCircle, { className: "mr-2 h-4 w-4 animate-spin" }) : /* @__PURE__ */ React169__namespace.default.createElement(Upload, { className: "mr-2 h-4 w-4" }), isImporting ? "Importing..." : "Select File"), /* @__PURE__ */ React169__namespace.default.createElement("input", { type: "file", ref: fileInputRef, onChange: handleFileSelected, accept: ".json,.tsv,.txt,text/tab-separated-values", className: "hidden" }))), /* @__PURE__ */ React169__namespace.default.createElement(TabsContent2, { value: "text", className: "pt-4" }, /* @__PURE__ */ React169__namespace.default.createElement("div", { className: "space-y-3" }, /* @__PURE__ */ React169__namespace.default.createElement(Label2, { htmlFor: "jsonInput" }, "JSON Data (Array of Objects)"), /* @__PURE__ */ React169__namespace.default.createElement(
138790
138790
  Textarea,
138791
138791
  {
138792
138792
  id: "jsonInput",
package/dist/react-ui.mjs CHANGED
@@ -138673,8 +138673,8 @@ function MetadataImportControls({ metadataName, onImport }) {
138673
138673
  const handleFileSelected = (event) => {
138674
138674
  const file = event.target.files?.[0];
138675
138675
  if (!file) return;
138676
- if (file.type !== "application/json" && !file.name.endsWith(".csv")) {
138677
- toast2({ title: "Invalid File Type", description: "Please select a JSON or CSV file.", variant: "destructive" });
138676
+ if (!file.type.includes("json") && !file.type.includes("tab-separated-values") && !file.name.endsWith(".tsv") && !file.name.endsWith(".txt")) {
138677
+ toast2({ title: "Invalid File Type", description: "Please select a JSON or TSV/TXT file.", variant: "destructive" });
138678
138678
  if (event.target) event.target.value = "";
138679
138679
  return;
138680
138680
  }
@@ -138682,18 +138682,18 @@ function MetadataImportControls({ metadataName, onImport }) {
138682
138682
  try {
138683
138683
  const fileContent = await file.text();
138684
138684
  let records = [];
138685
- if (file.type === "application/json") {
138685
+ if (file.type.includes("json")) {
138686
138686
  records = JSON.parse(fileContent);
138687
138687
  if (!Array.isArray(records)) throw new Error("JSON file must contain an array of objects.");
138688
- } else if (file.name.endsWith(".csv")) {
138689
- const lines = fileContent.split(/\r\n|\n/).filter((line) => line.trim() !== "");
138690
- if (lines.length < 2) throw new Error("CSV must have a header and at least one data row.");
138691
- const headers = lines[0].split(",").map((h3) => h3.trim());
138688
+ } else {
138689
+ const lines = fileContent.split(/\r?\n/).filter((line) => line.trim() !== "");
138690
+ if (lines.length < 2) throw new Error("TSV file must have a header and at least one data row.");
138691
+ const headers = lines[0].split(" ").map((h3) => h3.trim());
138692
138692
  records = lines.slice(1).map((line) => {
138693
- const values = line.split(",").map((v) => v.trim());
138693
+ const values = line.split(" ");
138694
138694
  const record = {};
138695
138695
  headers.forEach((header, index3) => {
138696
- record[header] = values[index3];
138696
+ record[header] = values[index3]?.trim() || "";
138697
138697
  });
138698
138698
  return record;
138699
138699
  });
@@ -138720,7 +138720,7 @@ function MetadataImportControls({ metadataName, onImport }) {
138720
138720
  }
138721
138721
  });
138722
138722
  };
138723
- return /* @__PURE__ */ React169__default.createElement(Dialog2, { open: isOpen, onOpenChange: setIsOpen }, /* @__PURE__ */ React169__default.createElement(DialogTrigger2, { asChild: true }, /* @__PURE__ */ React169__default.createElement(Button, { size: "sm", variant: "outline" }, /* @__PURE__ */ React169__default.createElement(Upload, { className: "mr-2 h-4 w-4" }), " Import ", metadataName)), /* @__PURE__ */ React169__default.createElement(DialogContent2, null, /* @__PURE__ */ React169__default.createElement(DialogHeader, null, /* @__PURE__ */ React169__default.createElement(DialogTitle2, null, "Bulk Import ", metadataName), /* @__PURE__ */ React169__default.createElement(DialogDescription2, null, "Import multiple records from a file or by pasting JSON data.")), /* @__PURE__ */ React169__default.createElement(Tabs2, { defaultValue: "file" }, /* @__PURE__ */ React169__default.createElement(TabsList2, { className: "grid w-full grid-cols-2" }, /* @__PURE__ */ React169__default.createElement(TabsTrigger2, { value: "file" }, /* @__PURE__ */ React169__default.createElement(FileJson, { className: "mr-2 h-4 w-4" }), " From File"), /* @__PURE__ */ React169__default.createElement(TabsTrigger2, { value: "text" }, /* @__PURE__ */ React169__default.createElement(ClipboardPaste, { className: "mr-2 h-4 w-4" }), " From Text")), /* @__PURE__ */ React169__default.createElement(TabsContent2, { value: "file", className: "pt-4" }, /* @__PURE__ */ React169__default.createElement("div", { className: "space-y-3" }, /* @__PURE__ */ React169__default.createElement("p", { className: "text-sm text-muted-foreground" }, "Select a JSON or CSV file. Ensure column names in the file match the table schema (e.g., 'code', 'name', 'subject_code')."), /* @__PURE__ */ React169__default.createElement(Button, { variant: "outline", onClick: () => fileInputRef.current?.click(), disabled: isImporting }, isImporting ? /* @__PURE__ */ React169__default.createElement(LoaderCircle, { className: "mr-2 h-4 w-4 animate-spin" }) : /* @__PURE__ */ React169__default.createElement(Upload, { className: "mr-2 h-4 w-4" }), isImporting ? "Importing..." : "Select File"), /* @__PURE__ */ React169__default.createElement("input", { type: "file", ref: fileInputRef, onChange: handleFileSelected, accept: ".json,.csv", className: "hidden" }))), /* @__PURE__ */ React169__default.createElement(TabsContent2, { value: "text", className: "pt-4" }, /* @__PURE__ */ React169__default.createElement("div", { className: "space-y-3" }, /* @__PURE__ */ React169__default.createElement(Label2, { htmlFor: "jsonInput" }, "JSON Data (Array of Objects)"), /* @__PURE__ */ React169__default.createElement(
138723
+ return /* @__PURE__ */ React169__default.createElement(Dialog2, { open: isOpen, onOpenChange: setIsOpen }, /* @__PURE__ */ React169__default.createElement(DialogTrigger2, { asChild: true }, /* @__PURE__ */ React169__default.createElement(Button, { size: "sm", variant: "outline" }, /* @__PURE__ */ React169__default.createElement(Upload, { className: "mr-2 h-4 w-4" }), " Import ", metadataName)), /* @__PURE__ */ React169__default.createElement(DialogContent2, null, /* @__PURE__ */ React169__default.createElement(DialogHeader, null, /* @__PURE__ */ React169__default.createElement(DialogTitle2, null, "Bulk Import ", metadataName), /* @__PURE__ */ React169__default.createElement(DialogDescription2, null, "Import multiple records from a file or by pasting JSON data.")), /* @__PURE__ */ React169__default.createElement(Tabs2, { defaultValue: "file" }, /* @__PURE__ */ React169__default.createElement(TabsList2, { className: "grid w-full grid-cols-2" }, /* @__PURE__ */ React169__default.createElement(TabsTrigger2, { value: "file" }, /* @__PURE__ */ React169__default.createElement(FileJson, { className: "mr-2 h-4 w-4" }), " From File"), /* @__PURE__ */ React169__default.createElement(TabsTrigger2, { value: "text" }, /* @__PURE__ */ React169__default.createElement(ClipboardPaste, { className: "mr-2 h-4 w-4" }), " From Text")), /* @__PURE__ */ React169__default.createElement(TabsContent2, { value: "file", className: "pt-4" }, /* @__PURE__ */ React169__default.createElement("div", { className: "space-y-3" }, /* @__PURE__ */ React169__default.createElement("p", { className: "text-sm text-muted-foreground" }, "Select a JSON or TSV/TXT file. Ensure column names in the file match the table schema (e.g., 'code', 'name', 'subjectCode')."), /* @__PURE__ */ React169__default.createElement(Button, { variant: "outline", onClick: () => fileInputRef.current?.click(), disabled: isImporting }, isImporting ? /* @__PURE__ */ React169__default.createElement(LoaderCircle, { className: "mr-2 h-4 w-4 animate-spin" }) : /* @__PURE__ */ React169__default.createElement(Upload, { className: "mr-2 h-4 w-4" }), isImporting ? "Importing..." : "Select File"), /* @__PURE__ */ React169__default.createElement("input", { type: "file", ref: fileInputRef, onChange: handleFileSelected, accept: ".json,.tsv,.txt,text/tab-separated-values", className: "hidden" }))), /* @__PURE__ */ React169__default.createElement(TabsContent2, { value: "text", className: "pt-4" }, /* @__PURE__ */ React169__default.createElement("div", { className: "space-y-3" }, /* @__PURE__ */ React169__default.createElement(Label2, { htmlFor: "jsonInput" }, "JSON Data (Array of Objects)"), /* @__PURE__ */ React169__default.createElement(
138724
138724
  Textarea,
138725
138725
  {
138726
138726
  id: "jsonInput",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@thanh01.pmt/interactive-quiz-kit",
3
- "version": "1.0.68",
3
+ "version": "1.0.69",
4
4
  "description": "A comprehensive library for creating, managing, and playing interactive quizzes, with AI generation and SCORM support.",
5
5
  "keywords": [
6
6
  "react",