@skalfa/skalfa-component 1.0.10 → 1.0.11

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.
@@ -7,8 +7,10 @@ const react_1 = require("react");
7
7
  const _utils_1 = require("@utils");
8
8
  const _components_1 = require("@components");
9
9
  const skalfa_icon_1 = require("@skalfa/skalfa-icon");
10
+ const skalfa_lang_1 = require("@skalfa/skalfa-lang");
10
11
  ;
11
12
  function ModalConfirmComponent({ show, title, children, footer, submitControl, onClose, className = "", }) {
13
+ const l = (0, skalfa_lang_1.useLang)();
12
14
  const { isSm } = (0, _utils_1.useResponsive)();
13
15
  const [toast, setToast] = (0, react_1.useState)(false);
14
16
  const [loading, setLoading] = (0, react_1.useState)(false);
@@ -28,12 +30,12 @@ function ModalConfirmComponent({ show, title, children, footer, submitControl, o
28
30
  }, [show]);
29
31
  const renderChildren = (actionSize = 'md') => {
30
32
  if (toast == "success") {
31
- return ((0, jsx_runtime_1.jsxs)("div", { className: "flex flex-col items-center justify-center h-full py-6 transition-all duration-300 animate-intro-down", children: [(0, jsx_runtime_1.jsx)("div", { className: "w-12 h-12 rounded-full bg-blue-50 flex items-center justify-center", children: (0, jsx_runtime_1.jsx)(skalfa_icon_1.Icon, { icon: "solid/check", className: "text-primary text-2xl" }) }), (0, jsx_runtime_1.jsx)("p", { className: "text-primary text-lg font-semibold mt-4", children: "Berhasil!" })] }));
33
+ return ((0, jsx_runtime_1.jsxs)("div", { className: "flex flex-col items-center justify-center h-full py-6 transition-all duration-300 animate-intro-down", children: [(0, jsx_runtime_1.jsx)("div", { className: "w-12 h-12 rounded-full bg-blue-50 flex items-center justify-center", children: (0, jsx_runtime_1.jsx)(skalfa_icon_1.Icon, { icon: "solid/check", className: "text-primary text-2xl" }) }), (0, jsx_runtime_1.jsx)("p", { className: "text-primary text-lg font-semibold mt-4", children: l.base.success ? l.base.success() : "Success" })] }));
32
34
  }
33
- return ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [title && ((0, jsx_runtime_1.jsx)("div", { className: (0, _utils_1.cn)("flex flex-col gap-2 p-6", (0, _utils_1.pcn)(className, "header")), children: (0, jsx_runtime_1.jsx)("h6", { className: "font-semibold text-lg", children: title }) })), children, toast == "failed" && ((0, jsx_runtime_1.jsx)("div", { className: "px-4", children: (0, jsx_runtime_1.jsxs)("div", { className: "mt-4 w-full p-4 rounded-sm border border-danger bg-light-danger flex gap-4 items-center", children: [(0, jsx_runtime_1.jsx)("div", { children: (0, jsx_runtime_1.jsx)("div", { className: "w-10 h-10 rounded-full bg-danger/20 flex items-center justify-center", children: (0, jsx_runtime_1.jsx)(skalfa_icon_1.Icon, { icon: "solid/exclamation-triangle", className: "text-danger text-lg" }) }) }), (0, jsx_runtime_1.jsx)("p", { className: "text-danger text-sm font-semibold", children: "Terjadi Masalah, Coba ulangi lagi!" })] }) })), renderAction(actionSize)] }));
35
+ return ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [title && ((0, jsx_runtime_1.jsx)("div", { className: (0, _utils_1.cn)("flex flex-col gap-2 p-6", (0, _utils_1.pcn)(className, "header")), children: (0, jsx_runtime_1.jsx)("h6", { className: "font-semibold text-lg", children: title }) })), children, toast == "failed" && ((0, jsx_runtime_1.jsx)("div", { className: "px-4", children: (0, jsx_runtime_1.jsxs)("div", { className: "mt-4 w-full p-4 rounded-sm border border-danger bg-light-danger flex gap-4 items-center", children: [(0, jsx_runtime_1.jsx)("div", { children: (0, jsx_runtime_1.jsx)("div", { className: "w-10 h-10 rounded-full bg-danger/20 flex items-center justify-center", children: (0, jsx_runtime_1.jsx)(skalfa_icon_1.Icon, { icon: "solid/exclamation-triangle", className: "text-danger text-lg" }) }) }), (0, jsx_runtime_1.jsx)("p", { className: "text-danger text-sm font-semibold", children: l.base.confirmFailed ? l.base.confirmFailed() : "Failed" })] }) })), renderAction(actionSize)] }));
34
36
  };
35
37
  const renderAction = (size = 'md') => {
36
- return ((0, jsx_runtime_1.jsxs)("div", { className: "flex justify-center gap-4 p-6 pt-2", children: [(0, jsx_runtime_1.jsx)(_components_1.ButtonComponent, { label: "Batal", variant: "outline", onClick: () => onClose(), block: true, size: size }), (0, jsx_runtime_1.jsx)(_components_1.ButtonComponent, { label: "Konfirmasi", loading: loading, onClick: async () => {
38
+ return ((0, jsx_runtime_1.jsxs)("div", { className: "flex justify-center gap-4 p-6 pt-2", children: [(0, jsx_runtime_1.jsx)(_components_1.ButtonComponent, { label: l.base.cancel ? l.base.cancel() : "", variant: "outline", onClick: () => onClose(), block: true, size: size }), (0, jsx_runtime_1.jsx)(_components_1.ButtonComponent, { label: l.base.confirm ? l.base.confirm() : "", loading: loading, onClick: async () => {
37
39
  if (!submitControl?.onSubmit)
38
40
  return;
39
41
  setLoading(true);
@@ -10,8 +10,6 @@ function TabbarComponent({ items, onChange, active,
10
10
  className = "", }) {
11
11
  return ((0, jsx_runtime_1.jsx)(jsx_runtime_1.Fragment, { children: (0, jsx_runtime_1.jsx)("div", { className: (0, _utils_1.cn)("tabbar-base", (0, _utils_1.pcn)(className, "base")), children: items?.map((item, i) => {
12
12
  const isItemActive = active == (typeof item != "string" ? item?.value : item);
13
- return ((0, jsx_runtime_1.jsx)("div", { className: (0, _utils_1.cn)("tabbar-item", isItemActive
14
- ? "tabbar-item-active"
15
- : "tabbar-item-inactive", (0, _utils_1.pcn)(className, "item"), (0, _utils_1.pcn)(className, "active")), onClick: () => onChange?.(typeof item != "string" ? item?.value : item), children: typeof item != "string" ? item?.label : item }, i));
13
+ return ((0, jsx_runtime_1.jsx)("div", { className: (0, _utils_1.cn)("tabbar-item", isItemActive ? "tabbar-item-active" : "tabbar-item-inactive", (0, _utils_1.pcn)(className, "item"), (0, _utils_1.pcn)(className, "active")), onClick: () => onChange?.(typeof item != "string" ? item?.value : item), children: typeof item != "string" ? item?.label : item }, i));
16
14
  }) }) }));
17
15
  }
@@ -116,7 +116,7 @@ function FormSupervisionComponent({ title, fields, submitControl, confirmation,
116
116
  });
117
117
  setValues(updatedValues);
118
118
  };
119
- return ((0, jsx_runtime_1.jsxs)("div", { className: (0, _utils_1.cn)("flex flex-col gap-4", generateColClass(form.col || "12")), children: [group.map((gIndex) => ((0, jsx_runtime_1.jsxs)("div", { className: (0, _utils_1.cn)("relative pr-8", wrap && "p-4 rounded border", className), children: [label && (0, jsx_runtime_1.jsxs)("p", { className: "input-label", children: [label, " ", gIndex + 1] }), tip && (0, jsx_runtime_1.jsx)("small", { className: (0, _utils_1.cn)("input-tip"), children: tip }), (label || tip) && (0, jsx_runtime_1.jsx)("div", { className: "mb-2" }), (0, jsx_runtime_1.jsx)("div", { className: "w-full grid grid-cols-12 gap-4", children: innerForms.map((inner, i) => renderInput(inner, i, `${mapName}[${gIndex}]`)) }), (0, jsx_runtime_1.jsx)(__1.ButtonComponent, { icon: "solid/times", paint: "danger", variant: "outline", size: "xs", className: (0, _utils_1.cn)("absolute top-10 right-2 translate-x-[50%] -translate-y-[50%]", wrap && "translate-x-0 -translate-y-0 top-1 right-1"), onClick: () => removeGroup(gIndex) })] }, gIndex))), (0, jsx_runtime_1.jsx)("div", { children: (0, jsx_runtime_1.jsx)(__1.ButtonComponent, { icon: "solid/plus", label: `Tambah ${label || mapName}`, variant: "outline", size: "sm", onClick: addGroup }) })] }, key));
119
+ return ((0, jsx_runtime_1.jsxs)("div", { className: (0, _utils_1.cn)("flex flex-col gap-4", generateColClass(form.col || "12")), children: [group.map((gIndex) => ((0, jsx_runtime_1.jsxs)("div", { className: (0, _utils_1.cn)("relative pr-8", wrap && "p-4 rounded border", className), children: [label && (0, jsx_runtime_1.jsxs)("p", { className: "input-label", children: [label, " ", gIndex + 1] }), tip && (0, jsx_runtime_1.jsx)("small", { className: (0, _utils_1.cn)("input-tip"), children: tip }), (label || tip) && (0, jsx_runtime_1.jsx)("div", { className: "mb-2" }), (0, jsx_runtime_1.jsx)("div", { className: "w-full grid grid-cols-12 gap-4", children: innerForms.map((inner, i) => renderInput(inner, i, `${mapName}[${gIndex}]`)) }), (0, jsx_runtime_1.jsx)(__1.ButtonComponent, { icon: "solid/times", paint: "danger", variant: "outline", size: "xs", className: (0, _utils_1.cn)("absolute top-10 right-2 translate-x-[50%] -translate-y-[50%]", wrap && "translate-x-0 -translate-y-0 top-1 right-1"), onClick: () => removeGroup(gIndex) })] }, gIndex))), (0, jsx_runtime_1.jsx)("div", { children: (0, jsx_runtime_1.jsx)(__1.ButtonComponent, { icon: "solid/plus", label: `${l.base.add ? l.base.add() : "Add"} ${label || mapName}`, variant: "outline", size: "sm", onClick: addGroup }) })] }, key));
120
120
  }
121
121
  if (inputType === "custom") {
122
122
  const customRender = form.construction;
@@ -125,5 +125,8 @@ function FormSupervisionComponent({ title, fields, submitControl, confirmation,
125
125
  const Component = inputMap[inputType] || __1.InputComponent;
126
126
  return ((0, jsx_runtime_1.jsx)("div", { className: (0, _utils_1.cn)(form.className, generateColClass(form.col || "12")), children: (0, jsx_runtime_1.jsx)(Component, { ...form.construction, ...formControl(name) }) }, key));
127
127
  };
128
- return ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [title && (0, jsx_runtime_1.jsx)("h4", { className: (0, _utils_1.cn)("text-lg font-semibold mb-4", (0, _utils_1.pcn)(className, "title")), children: title }), modal == "success" ? ((0, jsx_runtime_1.jsxs)("div", { className: "flex flex-col items-center justify-center h-full py-6 transition-all duration-300 animate-intro-down", children: [(0, jsx_runtime_1.jsx)("div", { className: "w-12 h-12 rounded-full bg-blue-50 flex items-center justify-center", children: (0, jsx_runtime_1.jsx)(skalfa_icon_1.Icon, { icon: "solid/check", className: "text-primary text-2xl" }) }), (0, jsx_runtime_1.jsx)("p", { className: "text-primary text-lg font-semibold mt-4", children: successMessage || "Berhasil disimpan!" })] })) : ((0, jsx_runtime_1.jsx)("form", { id: id, className: (0, _utils_1.cn)("flex flex-col h-full pb-8"), onSubmit: submit, children: (0, jsx_runtime_1.jsxs)("div", { className: (0, _utils_1.cn)("grid grid-cols-12 gap-4 flex-1 content-start", (0, _utils_1.pcn)(className, "base")), children: [fresh && fields.map((f, i) => renderInput(f, i)), !footerControl && ((0, jsx_runtime_1.jsx)("div", { className: "hidden md:block col-span-12", children: (0, jsx_runtime_1.jsx)("div", { className: "flex justify-end mt-4", children: (0, jsx_runtime_1.jsx)(__1.ButtonComponent, { type: "submit", label: l.base?.save ? l.base.save() : "Save", icon: "solid/save", loading: loading, className: (0, _utils_1.pcn)(className, "submit") }) }) })), !footerControl && ((0, jsx_runtime_1.jsx)("div", { className: "md:hidden col-span-12 mt-4", children: (0, jsx_runtime_1.jsx)(__1.ButtonComponent, { label: l.base?.save ? l.base.save() : "Save", icon: "solid/save", type: "submit", loading: loading, block: true, className: (0, _utils_1.pcn)(className, "submit") }) })), footerControl && ((0, jsx_runtime_1.jsx)("div", { className: "col-span-12", children: footerControl?.({ loading }) })), modal == "failed" && ((0, jsx_runtime_1.jsxs)("div", { className: "col-span-12 mt-4 w-full p-4 rounded-sm border border-danger bg-light-danger flex gap-4 items-center", children: [(0, jsx_runtime_1.jsx)("div", { children: (0, jsx_runtime_1.jsx)("div", { className: "w-10 h-10 rounded-full bg-danger/20 flex items-center justify-center", children: (0, jsx_runtime_1.jsx)(skalfa_icon_1.Icon, { icon: "solid/exclamation-triangle", className: "text-danger text-lg" }) }) }), (0, jsx_runtime_1.jsx)("p", { className: "text-danger text-sm font-semibold", children: "Terjadi Masalah, Coba ulangi lagi!" })] }))] }) })), (0, jsx_runtime_1.jsx)(__1.ModalConfirmComponent, { show: confirm.show, onClose: () => confirm.onClose(), title: l.base?.confirmTitle ? l.base.confirmTitle() : "Yakin", submitControl: { onSubmit: () => confirm?.onConfirm(), paint: "primary" } })] }));
128
+ (0, react_1.useEffect)(() => {
129
+ setModal(false);
130
+ }, [values]);
131
+ return ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [title && (0, jsx_runtime_1.jsx)("h4", { className: (0, _utils_1.cn)("text-lg font-semibold mb-4", (0, _utils_1.pcn)(className, "title")), children: title }), modal == "success" ? ((0, jsx_runtime_1.jsxs)("div", { className: "flex flex-col items-center justify-center h-full py-6 transition-all duration-300 animate-intro-down", children: [(0, jsx_runtime_1.jsx)("div", { className: "w-12 h-12 rounded-full bg-blue-50 flex items-center justify-center", children: (0, jsx_runtime_1.jsx)(skalfa_icon_1.Icon, { icon: "solid/check", className: "text-primary text-2xl" }) }), (0, jsx_runtime_1.jsx)("p", { className: "text-primary text-lg font-semibold mt-4", children: successMessage || l.base?.success ? l.base.success() : "Success!" })] })) : ((0, jsx_runtime_1.jsx)("form", { id: id, className: (0, _utils_1.cn)("flex flex-col h-full pb-8"), onSubmit: submit, children: (0, jsx_runtime_1.jsxs)("div", { className: (0, _utils_1.cn)("grid grid-cols-12 gap-4 flex-1 content-start", (0, _utils_1.pcn)(className, "base")), children: [fresh && fields.map((f, i) => renderInput(f, i)), !footerControl && ((0, jsx_runtime_1.jsx)("div", { className: "hidden md:block col-span-12", children: (0, jsx_runtime_1.jsx)("div", { className: "flex justify-end mt-4", children: (0, jsx_runtime_1.jsx)(__1.ButtonComponent, { type: "submit", label: l.base?.save ? l.base.save() : "Save", icon: "solid/save", loading: loading, className: (0, _utils_1.pcn)(className, "submit") }) }) })), !footerControl && ((0, jsx_runtime_1.jsx)("div", { className: "md:hidden col-span-12 mt-4", children: (0, jsx_runtime_1.jsx)(__1.ButtonComponent, { label: l.base?.save ? l.base.save() : "Save", icon: "solid/save", type: "submit", loading: loading, block: true, className: (0, _utils_1.pcn)(className, "submit") }) })), footerControl && ((0, jsx_runtime_1.jsx)("div", { className: "col-span-12", children: footerControl?.({ loading }) })), modal == "failed" && ((0, jsx_runtime_1.jsxs)("div", { className: "col-span-12 mt-4 w-full p-4 rounded-sm border border-danger bg-light-danger flex gap-4 items-center", children: [(0, jsx_runtime_1.jsx)("div", { children: (0, jsx_runtime_1.jsx)("div", { className: "w-10 h-10 rounded-full bg-danger/20 flex items-center justify-center", children: (0, jsx_runtime_1.jsx)(skalfa_icon_1.Icon, { icon: "solid/exclamation-triangle", className: "text-danger text-lg" }) }) }), (0, jsx_runtime_1.jsx)("p", { className: "text-danger text-sm font-semibold", children: l.base.formFailed ? l.base.formFailed() : "Failed to save data, please check your data and internet connection then try again!" })] }))] }) })), (0, jsx_runtime_1.jsx)(__1.ModalConfirmComponent, { show: confirm.show, onClose: () => confirm.onClose(), title: l.base?.formConfirm ? l.base.formConfirm() : "Are you sure all data is correct?", submitControl: { onSubmit: () => confirm?.onConfirm(), paint: "primary" } })] }));
129
132
  }
@@ -23,26 +23,26 @@ function TableSupervisionComponent({ title, id, fetchControl, columnControl, for
23
23
  _utils_1.shortcut.register("arrowdown", () => {
24
24
  const max = data?.data?.length - 1;
25
25
  setFocus(focus == null ? 0 : focus >= max ? max : (focus + 1));
26
- }, "Pilih data kebawah");
26
+ }, l.base.shortcutDown ? l.base.shortcutDown() : "");
27
27
  _utils_1.shortcut.register("arrowup", () => {
28
28
  setFocus(focus == null ? 0 : focus <= 0 ? 0 : (focus - 1));
29
- }, "Pilih data keatas");
29
+ }, l.base.shortcutUp ? l.base.shortcutUp() : "");
30
30
  if (focus != null) {
31
31
  _utils_1.shortcut.register("delete", () => {
32
32
  setSelected(data?.data?.at(focus));
33
33
  setToggle(`MODAL_DELETE_${toggleKey}`);
34
- }, "Delete data yang dipilih");
34
+ }, l.base.shortcutDelete ? l.base.shortcutDelete() : "");
35
35
  _utils_1.shortcut.register(" ", () => {
36
36
  setSelected(data?.data?.at(focus));
37
37
  setToggle(`MODAL_FORM_${toggleKey}`);
38
- }, "Edit data yang dipilih");
38
+ }, l.base.shortcutEdit ? l.base.shortcutEdit() : "");
39
39
  _utils_1.shortcut.register("enter", () => {
40
40
  setSelected(data?.data?.at(focus));
41
41
  setToggle(`MODAL_SHOW_${toggleKey}`);
42
- }, "Detail data yang dipilih");
42
+ }, l.base.shortcutDetail ? l.base.shortcutDetail() : "");
43
43
  _utils_1.shortcut.register("escape", () => {
44
44
  setFocus(null);
45
- }, "Kembali");
45
+ }, l.base.shortcutBack ? l.base.shortcutBack() : "");
46
46
  }
47
47
  }
48
48
  return () => {
@@ -166,7 +166,7 @@ function TableSupervisionComponent({ title, id, fetchControl, columnControl, for
166
166
  construction: {
167
167
  name: typeof col == "string" ? col : col?.selector,
168
168
  label: typeof col == "string" ? col : col?.label,
169
- placeholder: `Masukkan ${typeof col == "string" ? col : col?.label}...`,
169
+ placeholder: l.base.inputPlaceholder ? l.base.inputPlaceholder(`${typeof col == "string" ? col : col?.label}`) : `Enter ${typeof col == "string" ? col : col?.label}...`,
170
170
  },
171
171
  };
172
172
  }) || (data?.data?.at(0) ? Object.keys(data.data[0]).map((col) => {
@@ -176,7 +176,7 @@ function TableSupervisionComponent({ title, id, fetchControl, columnControl, for
176
176
  construction: {
177
177
  name: col,
178
178
  label: col,
179
- placeholder: `Masukkan ${col}...`,
179
+ placeholder: l.base.inputPlaceholder ? l.base.inputPlaceholder(col) : `Enter ${col}...`,
180
180
  },
181
181
  };
182
182
  })
@@ -205,24 +205,24 @@ function TableSupervisionComponent({ title, id, fetchControl, columnControl, for
205
205
  if (cb == "CREATE") {
206
206
  if (isSm)
207
207
  return;
208
- return ((0, jsx_runtime_1.jsx)("div", { className: "pl-1.5 pr-3 mr-2 border-r", children: (0, jsx_runtime_1.jsx)(__1.ButtonComponent, { icon: "solid/plus", label: "Tambah Data", size: "sm", onClick: () => {
208
+ return ((0, jsx_runtime_1.jsx)("div", { className: "pl-1.5 pr-3 mr-2 border-r", children: (0, jsx_runtime_1.jsx)(__1.ButtonComponent, { icon: "solid/plus", label: l.base.add ? l.base.add() : "Add", size: "sm", onClick: () => {
209
209
  setToggle(`MODAL_FORM_${toggleKey}`);
210
210
  setSelected(null);
211
211
  } }) }, "button-add"));
212
212
  }
213
213
  if (cb == "IMPORT") {
214
- return ((0, jsx_runtime_1.jsx)("div", { className: "px-1.5 rounded-md relative", children: (0, jsx_runtime_1.jsx)(__1.ButtonComponent, { icon: "solid/file-excel", label: "Import", variant: "outline", className: "!text-foreground", onClick: () => setToggle(`MODAL_IMPORT_${toggleKey}`), size: "sm" }) }, "import"));
214
+ return ((0, jsx_runtime_1.jsx)("div", { className: "px-1.5 rounded-md relative", children: (0, jsx_runtime_1.jsx)(__1.ButtonComponent, { icon: "solid/file-excel", variant: "outline", className: "!text-foreground", onClick: () => setToggle(`MODAL_IMPORT_${toggleKey}`), size: "sm" }) }, "import"));
215
215
  }
216
216
  if (cb == "EXPORT") {
217
- return ((0, jsx_runtime_1.jsx)("div", { className: "px-1.5 rounded-md relative", children: (0, jsx_runtime_1.jsx)(__1.ButtonComponent, { icon: "solid/file-excel", label: "Export", variant: "outline", className: "!text-foreground", onClick: () => setToggle(`MODAL_EXPORT_${toggleKey}`), size: "sm" }) }, "export-excel"));
217
+ return ((0, jsx_runtime_1.jsx)("div", { className: "px-1.5 rounded-md relative", children: (0, jsx_runtime_1.jsx)(__1.ButtonComponent, { icon: "solid/file-excel", variant: "outline", className: "!text-foreground", onClick: () => setToggle(`MODAL_EXPORT_${toggleKey}`), size: "sm" }) }, "export-excel"));
218
218
  }
219
219
  if (cb == "PRINT") {
220
- return ((0, jsx_runtime_1.jsx)("div", { className: "px-1.5 rounded-md relative", children: (0, jsx_runtime_1.jsx)(__1.ButtonComponent, { icon: "solid/file-pdf", label: "Cetak", variant: "outline", className: "!text-foreground", onClick: () => setToggle(`MODAL_PRINT_${toggleKey}`), size: "sm" }) }, "export-pdf"));
220
+ return ((0, jsx_runtime_1.jsx)("div", { className: "px-1.5 rounded-md relative", children: (0, jsx_runtime_1.jsx)(__1.ButtonComponent, { icon: "solid/file-pdf", label: l.base.print ? l.base.print() : "Print", variant: "outline", className: "!text-foreground", onClick: () => setToggle(`MODAL_PRINT_${toggleKey}`), size: "sm" }) }, "export-pdf"));
221
221
  }
222
222
  return cb;
223
223
  }) || [
224
224
  ...(!isSm ? [
225
- (0, jsx_runtime_1.jsx)("div", { className: "pl-1.5 pr-3 mr-2 border-r", children: (0, jsx_runtime_1.jsx)(__1.ButtonComponent, { icon: "solid/plus", label: "Tambah Data", size: "sm", onClick: () => {
225
+ (0, jsx_runtime_1.jsx)("div", { className: "pl-1.5 pr-3 mr-2 border-r", children: (0, jsx_runtime_1.jsx)(__1.ButtonComponent, { icon: "solid/plus", label: l.base.add ? l.base.add() : "Add", size: "sm", onClick: () => {
226
226
  setToggle(`MODAL_FORM_${toggleKey}`);
227
227
  setSelected(null);
228
228
  } }) }, "button-add")
@@ -255,13 +255,13 @@ function TableSupervisionComponent({ title, id, fetchControl, columnControl, for
255
255
  } : undefined, ...tableControl }), controlBar?.find((cb) => cb == "CREATE") && ((0, jsx_runtime_1.jsx)(__1.ButtonComponent, { icon: "solid/plus", className: "fixed bottom-24 right-4 w-14 h-14 z-20 md:hidden", size: "lg", rounded: true, onClick: () => {
256
256
  setToggle(`MODAL_FORM_${toggleKey}`);
257
257
  setSelected(null);
258
- } })), (0, jsx_runtime_1.jsx)(__1.FloatingPageComponent, { show: !!toggle[`MODAL_SHOW_${toggleKey}`], onClose: () => setToggle(`MODAL_SHOW_${toggleKey}`, false), title: "Detail", className: "bg-background", footer: renderTableAction(actionControl, undefined, { className: isSm ? "justify-end p-2 bg-background" : "justify-end", size: isSm ? "sm" : "md" }), children: detailPage }), (0, jsx_runtime_1.jsx)(__1.FloatingPageComponent, { show: !!toggle[`MODAL_FORM_${toggleKey}`], onClose: () => setToggle(`MODAL_FORM_${toggleKey}`, false), title: !!selected ? "Ubah Data" : "Tambah Data", className: (0, _utils_1.cn)("bg-white", formControl?.modalControl?.className), children: (0, jsx_runtime_1.jsx)("div", { className: "p-4", children: formPage }) }), (0, jsx_runtime_1.jsx)(__1.FloatingPageComponent, { show: !!toggle[`MODAL_EXPORT_${toggleKey}`], onClose: () => setToggle(`MODAL_EXPORT_${toggleKey}`, false), title: "Export Ke Excel", className: "bg-white md:w-[1200px] max-w-[1200px]", children: (0, jsx_runtime_1.jsx)(ExportExcel, { fetchControl: fetchControl, filename: "Export - " + title, columnControl: columns?.map((cc) => ({
258
+ } })), (0, jsx_runtime_1.jsx)(__1.FloatingPageComponent, { show: !!toggle[`MODAL_SHOW_${toggleKey}`], onClose: () => setToggle(`MODAL_SHOW_${toggleKey}`, false), title: l.base.detailTitle ? l.base.detailTitle() : "Detail", className: "bg-background", footer: renderTableAction(actionControl, undefined, { className: isSm ? "justify-end p-2 bg-background" : "justify-end", size: isSm ? "sm" : "md" }), children: detailPage }), (0, jsx_runtime_1.jsx)(__1.FloatingPageComponent, { show: !!toggle[`MODAL_FORM_${toggleKey}`], onClose: () => setToggle(`MODAL_FORM_${toggleKey}`, false), title: !!selected ? (l.base.editTitle ? l.base.editTitle() : "Edit") : (l.base.addTitle ? l.base.addTitle() : "Add"), className: (0, _utils_1.cn)("bg-white", formControl?.modalControl?.className), children: (0, jsx_runtime_1.jsx)("div", { className: "p-4", children: formPage }) }), (0, jsx_runtime_1.jsx)(__1.FloatingPageComponent, { show: !!toggle[`MODAL_EXPORT_${toggleKey}`], onClose: () => setToggle(`MODAL_EXPORT_${toggleKey}`, false), title: l.base.exportTitle ? l.base.exportTitle() : "Export", className: "bg-white md:w-[1200px] max-w-[1200px]", children: (0, jsx_runtime_1.jsx)(ExportExcel, { fetchControl: fetchControl, filename: "export", columnControl: columns?.map((cc) => ({
259
259
  label: cc.label || "",
260
260
  selector: cc.selector || "",
261
- })) }) }), (0, jsx_runtime_1.jsx)(__1.FloatingPageComponent, { show: !!toggle[`MODAL_IMPORT_${toggleKey}`], onClose: () => setToggle(`MODAL_IMPORT_${toggleKey}`, false), title: "Import Dari Excel", className: "bg-white md:w-[1200px] max-w-[1200px]", children: (0, jsx_runtime_1.jsx)(ImportExcel, { submitControl: { path: fetchControl?.path + "/import" }, columnControl: columns?.map((cc) => ({
261
+ })) }) }), (0, jsx_runtime_1.jsx)(__1.FloatingPageComponent, { show: !!toggle[`MODAL_IMPORT_${toggleKey}`], onClose: () => setToggle(`MODAL_IMPORT_${toggleKey}`, false), title: l.base.importTitle ? l.base.importTitle() : "Import", className: "bg-white md:w-[1200px] max-w-[1200px]", children: (0, jsx_runtime_1.jsx)(ImportExcel, { submitControl: { path: fetchControl?.path + "/import" }, columnControl: columns?.map((cc) => ({
262
262
  label: cc.label || "",
263
263
  selector: cc.selector || "",
264
- })) }) }), (0, jsx_runtime_1.jsx)(__1.ModalConfirmComponent, { show: !!toggle[`MODAL_DELETE_${toggleKey}`], onClose: () => setToggle(`MODAL_DELETE_${toggleKey}`, false), title: (0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: ["Menghapus Data ", (0, jsx_runtime_1.jsxs)("span", { className: "font-semibold", children: ["\"", selected?.[columns?.at(0)?.selector || ""], "\""] }), " ?"] }), submitControl: {
264
+ })) }) }), (0, jsx_runtime_1.jsx)(__1.ModalConfirmComponent, { show: !!toggle[`MODAL_DELETE_${toggleKey}`], onClose: () => setToggle(`MODAL_DELETE_${toggleKey}`, false), title: l.base.deleteTitle ? l.base.deleteTitle({ data: selected?.[columns?.at(0)?.selector || ""] }) : `Delete ${selected?.[columns?.at(0)?.selector || ""]}?`, submitControl: {
265
265
  onSubmit: {
266
266
  ...(fetchControl.path
267
267
  ? { path: `${fetchControl.path}/${selected?.id || ""}` }
@@ -14,7 +14,9 @@ const OutsideClick_component_1 = require("../wrap/OutsideClick.component");
14
14
  const Button_component_1 = require("../button/Button.component");
15
15
  const BottomSheet_component_1 = require("../modal/BottomSheet.component");
16
16
  const FilterComponent_1 = require("./FilterComponent");
17
+ const skalfa_lang_1 = require("@skalfa/skalfa-lang");
17
18
  function ControlBarComponent({ id = "", options, className, search, onSearch, searchableOptions, searchable, onSearchable, selectableOptions, selectable, onSelectable, sortableOptions, sort, onSort, filterableColumns, onFilter, filter, onRefresh }) {
19
+ const l = (0, skalfa_lang_1.useLang)();
18
20
  const { toggle, setToggle } = (0, _contexts_1.useToggleContext)();
19
21
  const { isSm } = (0, _utils_1.useResponsive)();
20
22
  const searchRef = (0, react_1.useRef)(null);
@@ -22,27 +24,27 @@ function ControlBarComponent({ id = "", options, className, search, onSearch, se
22
24
  if (options?.includes("SEARCH")) {
23
25
  _utils_1.shortcut.register("ctrl+s", () => {
24
26
  searchRef.current?.focus();
25
- }, "Cari");
27
+ }, l.base.shortcutSearch ? l.base.shortcutSearch() : "Search");
26
28
  }
27
29
  if (options?.includes("FILTER")) {
28
30
  _utils_1.shortcut.register("ctrl+f", () => {
29
31
  setToggle("FILTER");
30
- }, "Filter");
32
+ }, l.base.shortcutFilter ? l.base.shortcutFilter() : "Filter");
31
33
  }
32
34
  if (options?.includes("SORT")) {
33
35
  _utils_1.shortcut.register("ctrl+o", () => {
34
36
  setToggle("SORT");
35
- }, "Urutkan");
37
+ }, l.base.shortcutSort ? l.base.shortcutSort() : "Sort");
36
38
  }
37
39
  if (options?.includes("SELECTABLE")) {
38
40
  _utils_1.shortcut.register("ctrl+l", () => {
39
41
  setToggle("SELECTABLE");
40
- }, "Kolom Ditampilkan");
42
+ }, l.base.shortcutSelectable ? l.base.shortcutSelectable() : "Select");
41
43
  }
42
44
  if (options?.includes("REFRESH")) {
43
45
  _utils_1.shortcut.register("ctrl+shift+r", () => {
44
46
  onRefresh?.();
45
- }, "Refresh Tabel");
47
+ }, l.base.shortcutRefresh ? l.base.shortcutRefresh() : "Refresh");
46
48
  }
47
49
  return () => {
48
50
  options?.includes("SEARCH") && _utils_1.shortcut.unregister("ctrl+s");
@@ -78,7 +80,7 @@ function ControlBarComponent({ id = "", options, className, search, onSearch, se
78
80
  // =========================>
79
81
  }
80
82
  if (option == "CREATE") {
81
- return ((0, jsx_runtime_1.jsx)("div", { className: "control-bar-create-wrapper", children: (0, jsx_runtime_1.jsx)(Button_component_1.ButtonComponent, { icon: "solid/plus", label: "Tambah Data", size: "sm", onClick: () => setToggle(`MODAL_FORM_${_utils_1.conversion.strSnake(id).toUpperCase()}`) }) }, "button-add"));
83
+ return ((0, jsx_runtime_1.jsx)("div", { className: "control-bar-create-wrapper", children: (0, jsx_runtime_1.jsx)(Button_component_1.ButtonComponent, { icon: "solid/plus", label: l.base.add ? l.base.add() : "Add", size: "sm", onClick: () => setToggle(`MODAL_FORM_${_utils_1.conversion.strSnake(id).toUpperCase()}`) }) }, "button-add"));
82
84
  }
83
85
  {
84
86
  // =========================>
@@ -87,7 +89,7 @@ function ControlBarComponent({ id = "", options, className, search, onSearch, se
87
89
  }
88
90
  if (option == "SEARCH") {
89
91
  const searchable = !!options?.find((option) => option == "SEARCHABLE");
90
- return ((0, jsx_runtime_1.jsx)("div", { className: (0, _utils_1.cn)("control-bar-search-wrapper", searchable ? "control-bar-search-wrapper-searchable" : "control-bar-search-wrapper-standalone"), children: (0, jsx_runtime_1.jsx)(Input_component_1.InputComponent, { ref: searchRef, name: "search", placeholder: "Cari disini...", rightIcon: "solid/magnifying-glass", value: search, onChange: (e) => onSearch?.(e), className: (0, _utils_1.cn)("control-bar-search-input", searchable && "control-bar-search-input-searchable") }) }, key));
92
+ return ((0, jsx_runtime_1.jsx)("div", { className: (0, _utils_1.cn)("control-bar-search-wrapper", searchable ? "control-bar-search-wrapper-searchable" : "control-bar-search-wrapper-standalone"), children: (0, jsx_runtime_1.jsx)(Input_component_1.InputComponent, { ref: searchRef, name: "search", placeholder: l.base.searchPlaceholder ? l.base.searchPlaceholder() : "Search here...", rightIcon: "solid/magnifying-glass", value: search, onChange: (e) => onSearch?.(e), className: (0, _utils_1.cn)("control-bar-search-input", searchable && "control-bar-search-input-searchable") }) }, key));
91
93
  }
92
94
  {
93
95
  // =========================>
@@ -108,7 +110,7 @@ function ControlBarComponent({ id = "", options, className, search, onSearch, se
108
110
  // =========================>
109
111
  }
110
112
  if (option == "SELECTABLE") {
111
- return ((0, jsx_runtime_1.jsxs)("div", { className: "control-bar-button-wrapper", children: [(0, jsx_runtime_1.jsx)(Button_component_1.ButtonComponent, { icon: "solid/eye-low-vision", variant: "outline", className: "control-bar-icon-button", onClick: () => setToggle("SELECTABLE"), size: "sm" }), (0, jsx_runtime_1.jsx)(OutsideClick_component_1.OutsideClickComponent, { onOutsideClick: () => setToggle("SELECTABLE", false), children: (0, jsx_runtime_1.jsxs)("div", { className: (0, _utils_1.cn)("control-bar-dropdown", !toggle.SELECTABLE && "control-bar-dropdown-hidden"), children: [(0, jsx_runtime_1.jsx)("p", { className: 'control-bar-dropdown-title', children: "Kolom Ditampilkan" }), (0, jsx_runtime_1.jsx)(InputCheckbox_component_1.InputCheckboxComponent, { vertical: true, name: "show_column", options: selectableOptions?.map((option) => {
113
+ return ((0, jsx_runtime_1.jsxs)("div", { className: "control-bar-button-wrapper", children: [(0, jsx_runtime_1.jsx)(Button_component_1.ButtonComponent, { icon: "solid/eye-low-vision", variant: "outline", className: "control-bar-icon-button", onClick: () => setToggle("SELECTABLE"), size: "sm" }), (0, jsx_runtime_1.jsx)(OutsideClick_component_1.OutsideClickComponent, { onOutsideClick: () => setToggle("SELECTABLE", false), children: (0, jsx_runtime_1.jsxs)("div", { className: (0, _utils_1.cn)("control-bar-dropdown", !toggle.SELECTABLE && "control-bar-dropdown-hidden"), children: [(0, jsx_runtime_1.jsx)("p", { className: 'control-bar-dropdown-title', children: l.base.selectable ? l.base.selectable() : "Show Column" }), (0, jsx_runtime_1.jsx)(InputCheckbox_component_1.InputCheckboxComponent, { vertical: true, name: "show_column", options: selectableOptions?.map((option) => {
112
114
  return {
113
115
  label: option.label,
114
116
  value: option.selector,
@@ -121,7 +123,7 @@ function ControlBarComponent({ id = "", options, className, search, onSearch, se
121
123
  // =========================>
122
124
  }
123
125
  if (option == "SORT") {
124
- return sortableOptions?.length ? ((0, jsx_runtime_1.jsxs)("div", { className: "control-bar-button-wrapper", children: [(0, jsx_runtime_1.jsx)(Button_component_1.ButtonComponent, { icon: "solid/sort", variant: "outline", className: "control-bar-icon-button", onClick: () => setToggle("SORT"), size: "sm" }), (0, jsx_runtime_1.jsx)(OutsideClick_component_1.OutsideClickComponent, { onOutsideClick: () => setToggle("SORT", false), children: (0, jsx_runtime_1.jsxs)("div", { className: (0, _utils_1.cn)("control-bar-dropdown", !toggle.SORT && "control-bar-dropdown-hidden"), children: [(0, jsx_runtime_1.jsx)("p", { className: 'control-bar-dropdown-title', children: "Urut Berdasarkan" }), (0, jsx_runtime_1.jsx)("div", { className: 'control-bar-sort-list', children: sortableOptions?.map((option, key) => {
126
+ return sortableOptions?.length ? ((0, jsx_runtime_1.jsxs)("div", { className: "control-bar-button-wrapper", children: [(0, jsx_runtime_1.jsx)(Button_component_1.ButtonComponent, { icon: "solid/sort", variant: "outline", className: "control-bar-icon-button", onClick: () => setToggle("SORT"), size: "sm" }), (0, jsx_runtime_1.jsx)(OutsideClick_component_1.OutsideClickComponent, { onOutsideClick: () => setToggle("SORT", false), children: (0, jsx_runtime_1.jsxs)("div", { className: (0, _utils_1.cn)("control-bar-dropdown", !toggle.SORT && "control-bar-dropdown-hidden"), children: [(0, jsx_runtime_1.jsx)("p", { className: 'control-bar-dropdown-title', children: l.base.sort ? l.base.sort() : "Sort By" }), (0, jsx_runtime_1.jsx)("div", { className: 'control-bar-sort-list', children: sortableOptions?.map((option, key) => {
125
127
  const sortBy = sort?.find((s) => s.split(" ")?.at(0) == option?.selector)?.split(" ")?.at(1) || "";
126
128
  return ((0, jsx_runtime_1.jsxs)("div", { className: (0, _utils_1.cn)('control-bar-sort-item', !!sortBy && "control-bar-sort-item-active"), onClick: () => onChangeSort(option.selector), children: [(0, jsx_runtime_1.jsx)("p", { children: option.label }), sortBy && ((0, jsx_runtime_1.jsxs)("div", { className: 'control-bar-sort-active-icon', children: [(0, jsx_runtime_1.jsx)(skalfa_icon_1.Icon, { icon: sortBy == "desc" ? "solid/arrow-down-z-a" : "solid/arrow-up-a-z", className: 'control-bar-sort-icon' }), sort?.length && sort?.length > 1 && (0, jsx_runtime_1.jsx)("span", { className: 'control-bar-sort-badge', children: sort.findIndex((s) => s.split(" ")?.at(0) == option?.selector) + 1 })] }))] }, key));
127
129
  }) })] }) })] }, key)) : (0, jsx_runtime_1.jsx)(jsx_runtime_1.Fragment, {});
@@ -158,7 +160,7 @@ function ControlBarComponent({ id = "", options, className, search, onSearch, se
158
160
  // =========================>
159
161
  }
160
162
  if (option == "SEARCH") {
161
- return ((0, jsx_runtime_1.jsx)("div", { children: (0, jsx_runtime_1.jsx)(Input_component_1.InputComponent, { name: "search", placeholder: "Cari disini...", rightIcon: "solid/magnifying-glass", value: search, onChange: (e) => onSearch?.(e) }) }, key));
163
+ return ((0, jsx_runtime_1.jsx)("div", { children: (0, jsx_runtime_1.jsx)(Input_component_1.InputComponent, { name: "search", placeholder: l.base.searchPlaceholder ? l.base.searchPlaceholder() : "Search here...", rightIcon: "solid/magnifying-glass", value: search, onChange: (e) => onSearch?.(e) }) }, key));
162
164
  }
163
165
  {
164
166
  // =========================>
@@ -179,7 +181,7 @@ function ControlBarComponent({ id = "", options, className, search, onSearch, se
179
181
  // =========================>
180
182
  }
181
183
  if (option == "SELECTABLE") {
182
- return ((0, jsx_runtime_1.jsxs)("div", { children: [(0, jsx_runtime_1.jsx)("p", { className: 'control-bar-mobile-title', children: "Kolom Ditampilkan" }), (0, jsx_runtime_1.jsx)(InputCheckbox_component_1.InputCheckboxComponent, { vertical: true, name: "show_column", options: selectableOptions?.map((option) => {
184
+ return ((0, jsx_runtime_1.jsxs)("div", { children: [(0, jsx_runtime_1.jsx)("p", { className: 'control-bar-mobile-title', children: l.base.selectable ? l.base.selectable() : "Show Column" }), (0, jsx_runtime_1.jsx)(InputCheckbox_component_1.InputCheckboxComponent, { vertical: true, name: "show_column", options: selectableOptions?.map((option) => {
183
185
  return {
184
186
  label: option.label,
185
187
  value: option.selector,
@@ -192,7 +194,7 @@ function ControlBarComponent({ id = "", options, className, search, onSearch, se
192
194
  // =========================>
193
195
  }
194
196
  if (option == "SORT") {
195
- return sortableOptions?.length ? ((0, jsx_runtime_1.jsxs)("div", { children: [(0, jsx_runtime_1.jsx)("p", { className: 'control-bar-mobile-title', children: "Urut Berdasarkan" }), (0, jsx_runtime_1.jsx)("div", { className: 'flex flex-col', children: sortableOptions?.map((option, key) => {
197
+ return sortableOptions?.length ? ((0, jsx_runtime_1.jsxs)("div", { children: [(0, jsx_runtime_1.jsx)("p", { className: 'control-bar-mobile-title', children: l.base.sort ? l.base.sort() : "Sort By" }), (0, jsx_runtime_1.jsx)("div", { className: 'flex flex-col', children: sortableOptions?.map((option, key) => {
196
198
  const sortBy = sort?.find((s) => s.split(" ")?.at(0) == option?.selector)?.split(" ")?.at(1) || "";
197
199
  return ((0, jsx_runtime_1.jsxs)("div", { className: (0, _utils_1.cn)('control-bar-mobile-sort-item', !!sortBy && "control-bar-mobile-sort-item-active"), onClick: () => onChangeSort(option.selector), children: [(0, jsx_runtime_1.jsx)("p", { children: option.label }), sortBy && ((0, jsx_runtime_1.jsxs)("div", { className: 'text-primary', children: [(0, jsx_runtime_1.jsx)(skalfa_icon_1.Icon, { icon: sortBy == "desc" ? "solid/arrow-down-z-a" : "solid/arrow-up-a-z", className: 'text-xs' }), sort?.length && sort?.length > 1 && (0, jsx_runtime_1.jsx)("span", { className: 'text-[9px] ml-1', children: sort.findIndex((s) => s.split(" ")?.at(0) == option?.selector) + 1 })] }))] }, key));
198
200
  }) })] }, key)) : (0, jsx_runtime_1.jsx)(jsx_runtime_1.Fragment, {});
@@ -15,6 +15,7 @@ const InputNumber_component_1 = require("../input/InputNumber.component");
15
15
  const Modal_component_1 = require("../modal/Modal.component");
16
16
  const Select_component_1 = require("../input/Select.component");
17
17
  const _contexts_1 = require("@contexts");
18
+ const skalfa_lang_1 = require("@skalfa/skalfa-lang");
18
19
  const FILTER_OPERATORS = [
19
20
  { label: "Cari", value: "li" },
20
21
  { label: "Sama", value: "eq" },
@@ -29,6 +30,7 @@ const LOGIC_OPTIONS = [
29
30
  ];
30
31
  const BOOKMARK_KEY = "filter-bookmarks";
31
32
  function FilterComponent({ columns, onChange, value, onMinimize, className = "", }) {
33
+ const l = (0, skalfa_lang_1.useLang)();
32
34
  const { isSm } = (0, _utils_1.useResponsive)();
33
35
  const { toggle, setToggle } = (0, _contexts_1.useToggleContext)();
34
36
  const [filters, setFilters] = (0, react_1.useState)([]);
@@ -63,16 +65,16 @@ function FilterComponent({ columns, onChange, value, onMinimize, className = "",
63
65
  (0, react_1.useEffect)(() => {
64
66
  localStorage.setItem(BOOKMARK_KEY, JSON.stringify(bookmarks));
65
67
  }, [bookmarks]);
66
- return ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsxs)("div", { className: (0, _utils_1.cn)("filter-panel", (0, _utils_1.pcn)(className, "base")), children: [(0, jsx_runtime_1.jsxs)("div", { className: "filter-panel-header", children: [(0, jsx_runtime_1.jsx)("p", { className: (0, _utils_1.cn)((0, _utils_1.pcn)(className, "title")), children: "Filter" }), (0, jsx_runtime_1.jsxs)("div", { className: "filter-panel-controls", children: [(0, jsx_runtime_1.jsxs)("div", { className: "filter-panel-bookmarks-wrapper", children: [(0, jsx_runtime_1.jsx)(Button_component_1.ButtonComponent, { icon: "solid/bookmark", variant: "outline", paint: "primary", className: "filter-panel-bookmark-btn icon::text-slate-400", size: "xs", onClick: () => setToggle("MODAL_BOOKMARK", { bookmark_id: "new" }) }), !!bookmarks?.length && ((0, jsx_runtime_1.jsx)(Chip_component_1.ChipComponent, { items: bookmarks.slice(0, 5).map((b) => b.name), onClick: (_, index) => setFilters(bookmarks[index]?.filters), onDelete: (_, index) => setBookmarks(bookmarks.filter((_, bi) => bi != index)) })), bookmarks?.length > 5 && ((0, jsx_runtime_1.jsx)(Button_component_1.ButtonComponent, { icon: "solid/ellipsis-h", variant: "outline", paint: "primary", className: "filter-panel-bookmark-btn icon::text-slate-400", size: "xs", onClick: () => setToggle("MODAL_BOOKMARK_LIST") }))] }), (0, jsx_runtime_1.jsx)(Button_component_1.ButtonComponent, { icon: "solid/rotate", label: "Bersihkan", variant: "outline", paint: "primary", className: "filter-panel-bookmark-btn icon::text-slate-400", size: "xs", onClick: () => setFilters([]) }), onMinimize && ((0, jsx_runtime_1.jsx)(Button_component_1.ButtonComponent, { icon: "solid/chevron-up", variant: "outline", paint: "primary", className: "filter-panel-bookmark-btn icon::text-slate-400", size: "xs", onClick: onMinimize }))] })] }), filters.map((f, i) => {
68
+ return ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsxs)("div", { className: (0, _utils_1.cn)("filter-panel", (0, _utils_1.pcn)(className, "base")), children: [(0, jsx_runtime_1.jsxs)("div", { className: "filter-panel-header", children: [(0, jsx_runtime_1.jsx)("p", { className: (0, _utils_1.cn)((0, _utils_1.pcn)(className, "title")), children: l.base.filter ? l.base.filter() : "Filter" }), (0, jsx_runtime_1.jsxs)("div", { className: "filter-panel-controls", children: [(0, jsx_runtime_1.jsxs)("div", { className: "filter-panel-bookmarks-wrapper", children: [(0, jsx_runtime_1.jsx)(Button_component_1.ButtonComponent, { icon: "solid/bookmark", variant: "outline", paint: "primary", className: "filter-panel-bookmark-btn icon::text-slate-400", size: "xs", onClick: () => setToggle("MODAL_BOOKMARK", { bookmark_id: "new" }) }), !!bookmarks?.length && ((0, jsx_runtime_1.jsx)(Chip_component_1.ChipComponent, { items: bookmarks.slice(0, 5).map((b) => b.name), onClick: (_, index) => setFilters(bookmarks[index]?.filters), onDelete: (_, index) => setBookmarks(bookmarks.filter((_, bi) => bi != index)) })), bookmarks?.length > 5 && ((0, jsx_runtime_1.jsx)(Button_component_1.ButtonComponent, { icon: "solid/ellipsis-h", variant: "outline", paint: "primary", className: "filter-panel-bookmark-btn icon::text-slate-400", size: "xs", onClick: () => setToggle("MODAL_BOOKMARK_LIST") }))] }), (0, jsx_runtime_1.jsx)(Button_component_1.ButtonComponent, { icon: "solid/rotate", label: l.base.clear ? l.base.clear() : "Filter", variant: "outline", paint: "primary", className: "filter-panel-bookmark-btn icon::text-slate-400", size: "xs", onClick: () => setFilters([]) }), onMinimize && ((0, jsx_runtime_1.jsx)(Button_component_1.ButtonComponent, { icon: "solid/chevron-up", variant: "outline", paint: "primary", className: "filter-panel-bookmark-btn icon::text-slate-400", size: "xs", onClick: onMinimize }))] })] }), filters.map((f, i) => {
67
69
  const column = columns.find((c) => c.selector === f.column);
68
- return ((0, jsx_runtime_1.jsxs)("div", { className: "filter-row", children: [i > 0 && ((0, jsx_runtime_1.jsx)("div", { className: "filter-col-logic", children: (0, jsx_runtime_1.jsx)(Select_component_1.SelectComponent, { name: `filter_logic_${i}`, options: LOGIC_OPTIONS, placeholder: "Dan/Atau", value: f.logic, onChange: (e) => handleChange(i, "logic", e), className: "filter-input-field" }) })), (0, jsx_runtime_1.jsx)("div", { className: i > 0 ? "filter-col-column-with-logic" : "filter-col-column", children: (0, jsx_runtime_1.jsx)(Select_component_1.SelectComponent, { name: `filter_column_${i}`, options: columns.map((c) => ({
70
+ return ((0, jsx_runtime_1.jsxs)("div", { className: "filter-row", children: [i > 0 && ((0, jsx_runtime_1.jsx)("div", { className: "filter-col-logic", children: (0, jsx_runtime_1.jsx)(Select_component_1.SelectComponent, { name: `filter_logic_${i}`, options: LOGIC_OPTIONS, placeholder: l.base.filterLogic ? l.base.filterLogic() : "And/Or", value: f.logic, onChange: (e) => handleChange(i, "logic", e), className: "filter-input-field" }) })), (0, jsx_runtime_1.jsx)("div", { className: i > 0 ? "filter-col-column-with-logic" : "filter-col-column", children: (0, jsx_runtime_1.jsx)(Select_component_1.SelectComponent, { name: `filter_column_${i}`, options: columns.map((c) => ({
69
71
  label: c.label,
70
72
  value: c.selector,
71
- })), placeholder: "Kolom", value: f.column, onChange: (e) => handleChange(i, "column", e), className: "filter-input-field" }) }), (0, jsx_runtime_1.jsx)("div", { className: "filter-col-operator", children: (0, jsx_runtime_1.jsx)(Select_component_1.SelectComponent, { name: `filter_operator_${i}`, options: FILTER_OPERATORS, placeholder: "Operator", value: f.type, onChange: (e) => handleChange(i, "type", e), className: "filter-input-field" }) }), isSm && ((0, jsx_runtime_1.jsx)(Button_component_1.ButtonComponent, { icon: "solid/times", paint: "danger", variant: "outline", onClick: () => removeFilter(i), size: "xs" })), column && ((0, jsx_runtime_1.jsx)("div", { className: "filter-col-value", children: (0, jsx_runtime_1.jsx)(InputFilterValueComponent, { type: column.type, name: `filter_value_${i}`, placeholder: "...", value: f.value || "", onChange: (e) => handleChange(i, "value", e), options: column.type === "select" && column.options ? column.options : [], className: "filter-input-field", between: f.type === "bw", multiple: ["in", "ni"].includes(f.type || "") }) })), !isSm && ((0, jsx_runtime_1.jsx)(Button_component_1.ButtonComponent, { icon: "solid/times", paint: "danger", variant: "outline", onClick: () => removeFilter(i), size: "xs" }))] }, i));
72
- }), (0, jsx_runtime_1.jsx)(Button_component_1.ButtonComponent, { label: "Tambahkan", icon: "solid/plus", variant: "outline", paint: "primary", size: isSm ? "xs" : "sm", onClick: addFilter, className: "filter-add-btn" })] }), (0, jsx_runtime_1.jsx)(Modal_component_1.ModalComponent, { show: !!toggle["MODAL_BOOKMARK_LIST"], onClose: () => setToggle("MODAL_BOOKMARK_LIST", false), title: "Bookmark Filter", children: (0, jsx_runtime_1.jsx)("div", { className: "filter-bookmark-list-container", children: bookmarks?.length ? bookmarks?.map((b, key) => ((0, jsx_runtime_1.jsxs)("div", { className: "filter-bookmark-row", children: [(0, jsx_runtime_1.jsx)("p", { className: "filter-bookmark-name", children: b.name }), (0, jsx_runtime_1.jsxs)("div", { className: "flex gap-2", children: [(0, jsx_runtime_1.jsx)(Button_component_1.ButtonComponent, { icon: "solid/plus", variant: "outline", paint: "primary", className: "", size: "xs", onClick: () => {
73
+ })), placeholder: l.base.column ? l.base.column() : "Column", value: f.column, onChange: (e) => handleChange(i, "column", e), className: "filter-input-field" }) }), (0, jsx_runtime_1.jsx)("div", { className: "filter-col-operator", children: (0, jsx_runtime_1.jsx)(Select_component_1.SelectComponent, { name: `filter_operator_${i}`, options: FILTER_OPERATORS, placeholder: l.base.filterOperator ? l.base.filterOperator() : "Operation", value: f.type, onChange: (e) => handleChange(i, "type", e), className: "filter-input-field" }) }), isSm && ((0, jsx_runtime_1.jsx)(Button_component_1.ButtonComponent, { icon: "solid/times", paint: "danger", variant: "outline", onClick: () => removeFilter(i), size: "xs" })), column && ((0, jsx_runtime_1.jsx)("div", { className: "filter-col-value", children: (0, jsx_runtime_1.jsx)(InputFilterValueComponent, { type: column.type, name: `filter_value_${i}`, placeholder: "...", value: f.value || "", onChange: (e) => handleChange(i, "value", e), options: column.type === "select" && column.options ? column.options : [], className: "filter-input-field", between: f.type === "bw", multiple: ["in", "ni"].includes(f.type || "") }) })), !isSm && ((0, jsx_runtime_1.jsx)(Button_component_1.ButtonComponent, { icon: "solid/times", paint: "danger", variant: "outline", onClick: () => removeFilter(i), size: "xs" }))] }, i));
74
+ }), (0, jsx_runtime_1.jsx)(Button_component_1.ButtonComponent, { label: l.base.add ? l.base.add() : "Add", icon: "solid/plus", variant: "outline", paint: "primary", size: isSm ? "xs" : "sm", onClick: addFilter, className: "filter-add-btn" })] }), (0, jsx_runtime_1.jsx)(Modal_component_1.ModalComponent, { show: !!toggle["MODAL_BOOKMARK_LIST"], onClose: () => setToggle("MODAL_BOOKMARK_LIST", false), title: l.base.filterBookmarks ? l.base.filterBookmarks() : "Filter Bookmark", children: (0, jsx_runtime_1.jsx)("div", { className: "filter-bookmark-list-container", children: bookmarks?.length ? bookmarks?.map((b, key) => ((0, jsx_runtime_1.jsxs)("div", { className: "filter-bookmark-row", children: [(0, jsx_runtime_1.jsx)("p", { className: "filter-bookmark-name", children: b.name }), (0, jsx_runtime_1.jsxs)("div", { className: "flex gap-2", children: [(0, jsx_runtime_1.jsx)(Button_component_1.ButtonComponent, { icon: "solid/plus", variant: "outline", paint: "primary", className: "", size: "xs", onClick: () => {
73
75
  setFilters(b.filters);
74
76
  setToggle("MODAL_BOOKMARK_LIST", false);
75
- } }), (0, jsx_runtime_1.jsx)(Button_component_1.ButtonComponent, { icon: "solid/times", variant: "outline", paint: "danger", className: "", size: "xs", onClick: () => setBookmarks(bookmarks.filter((_, bi) => bi != key)) })] })] }, key))) : ((0, jsx_runtime_1.jsx)("div", { className: "filter-bookmark-empty-text", children: " -- Tidak ada Bookmark --" })) }) }), (0, jsx_runtime_1.jsx)(Modal_component_1.ModalComponent, { show: !!toggle["MODAL_BOOKMARK"], onClose: () => setToggle("MODAL_BOOKMARK", false), title: "Bookmark Filter", footer: (0, jsx_runtime_1.jsx)("div", { className: "flex justify-end", children: (0, jsx_runtime_1.jsx)(Button_component_1.ButtonComponent, { label: "Terapkan", onClick: () => {
77
+ } }), (0, jsx_runtime_1.jsx)(Button_component_1.ButtonComponent, { icon: "solid/times", variant: "outline", paint: "danger", className: "", size: "xs", onClick: () => setBookmarks(bookmarks.filter((_, bi) => bi != key)) })] })] }, key))) : ((0, jsx_runtime_1.jsxs)("div", { className: "filter-bookmark-empty-text", children: [" -- ", l.base.filterBookmarkEmpty ? l.base.filterBookmarkEmpty() : "No Bookmark", " --"] })) }) }), (0, jsx_runtime_1.jsx)(Modal_component_1.ModalComponent, { show: !!toggle["MODAL_BOOKMARK"], onClose: () => setToggle("MODAL_BOOKMARK", false), title: l.base.filterBookmark ? l.base.filterBookmark() : "Filter Bookmark", footer: (0, jsx_runtime_1.jsx)("div", { className: "flex justify-end", children: (0, jsx_runtime_1.jsx)(Button_component_1.ButtonComponent, { label: l.base.apply ? l.base.apply() : "Apply", onClick: () => {
76
78
  let updated = [];
77
79
  if (toggle["MODAL_BOOKMARK"]?.bookmark_id == "new") {
78
80
  const newBookmark = {
@@ -90,18 +92,19 @@ function FilterComponent({ columns, onChange, value, onMinimize, className = "",
90
92
  }
91
93
  setBookmarks(updated);
92
94
  setToggle("MODAL_BOOKMARK", false);
93
- } }) }), children: (0, jsx_runtime_1.jsxs)("div", { className: "filter-bookmark-form-container", children: [(0, jsx_runtime_1.jsx)(Select_component_1.SelectComponent, { name: `bookmark_id`, placeholder: "Pilih bookmark filter...", value: toggle["MODAL_BOOKMARK"]?.bookmark_id ?? "", onChange: e => setToggle("MODAL_BOOKMARK", { ...toggle["MODAL_BOOKMARK"], bookmark_id: e }), options: [
95
+ } }) }), children: (0, jsx_runtime_1.jsxs)("div", { className: "filter-bookmark-form-container", children: [(0, jsx_runtime_1.jsx)(Select_component_1.SelectComponent, { name: `bookmark_id`, placeholder: l.base.filterBookmarkPlaceholder ? l.base.filterBookmarkPlaceholder() : "Pilih bookmark filter...", value: toggle["MODAL_BOOKMARK"]?.bookmark_id ?? "", onChange: e => setToggle("MODAL_BOOKMARK", { ...toggle["MODAL_BOOKMARK"], bookmark_id: e }), options: [
94
96
  {
95
- label: "-- BOOKMARK BARU --",
97
+ label: `-- ${l.base.filterBookmarkNew ? l.base.filterBookmarkNew() : "New Filter Bookmark"} --`,
96
98
  value: "new",
97
99
  },
98
100
  ...bookmarks.map((b) => ({
99
101
  label: b.name,
100
102
  value: b.id,
101
103
  }))
102
- ] }), toggle["MODAL_BOOKMARK"]?.bookmark_id == "new" && ((0, jsx_runtime_1.jsx)(Input_component_1.InputComponent, { name: "bookmark_name", placeholder: "Masukkan nama bookmark...", value: toggle["MODAL_BOOKMARK"]?.bookmark_name ?? "", onChange: e => setToggle("MODAL_BOOKMARK", { ...toggle["MODAL_BOOKMARK"], bookmark_name: e }), className: "filter-bookmark-form-input" }))] }) })] }));
104
+ ] }), toggle["MODAL_BOOKMARK"]?.bookmark_id == "new" && ((0, jsx_runtime_1.jsx)(Input_component_1.InputComponent, { name: "bookmark_name", placeholder: l.base.filterBookmarkNewPlaceholder ? l.base.filterBookmarkNewPlaceholder() : "Masukkan nama bookmark...", value: toggle["MODAL_BOOKMARK"]?.bookmark_name ?? "", onChange: e => setToggle("MODAL_BOOKMARK", { ...toggle["MODAL_BOOKMARK"], bookmark_name: e }), className: "filter-bookmark-form-input" }))] }) })] }));
103
105
  }
104
106
  function InputFilterValueComponent({ type, name, value, onChange, options = [], placeholder = "", className = "", between, multiple, }) {
107
+ const l = (0, skalfa_lang_1.useLang)();
105
108
  const resolvedType = type || "text";
106
109
  if (!between) {
107
110
  switch (resolvedType) {
@@ -124,13 +127,13 @@ function InputFilterValueComponent({ type, name, value, onChange, options = [],
124
127
  const handle = (v) => onChange(pos === "from" ? [v, to] : [from, v]);
125
128
  switch (resolvedType) {
126
129
  case "number":
127
- return ((0, jsx_runtime_1.jsx)(InputNumber_component_1.InputNumberComponent, { name: `${name}_${pos}`, value: Number(currentValue) || 0, onChange: handle, placeholder: pos === "from" ? "Dari" : "Sampai", className: className }));
130
+ return ((0, jsx_runtime_1.jsx)(InputNumber_component_1.InputNumberComponent, { name: `${name}_${pos}`, value: Number(currentValue) || 0, onChange: handle, placeholder: pos === "from" ? l.base.filterFrom ? l.base.filterFrom() : "Dari" : l.base.filterTo ? l.base.filterTo() : "Sampai", className: className }));
128
131
  case "currency":
129
- return ((0, jsx_runtime_1.jsx)(InputCurrency_component_1.InputCurrencyComponent, { name: `${name}_${pos}`, value: Number(currentValue) || 0, onChange: handle, placeholder: pos === "from" ? "Dari" : "Sampai", className: className }));
132
+ return ((0, jsx_runtime_1.jsx)(InputCurrency_component_1.InputCurrencyComponent, { name: `${name}_${pos}`, value: Number(currentValue) || 0, onChange: handle, placeholder: pos === "from" ? l.base.filterFrom ? l.base.filterFrom() : "Dari" : l.base.filterTo ? l.base.filterTo() : "Sampai", className: className }));
130
133
  case "date":
131
- return ((0, jsx_runtime_1.jsx)(InputDate_component_1.InputDateComponent, { name: `${name}_${pos}`, value: currentValue || "", onChange: handle, placeholder: pos === "from" ? "Dari" : "Sampai", className: className }));
134
+ return ((0, jsx_runtime_1.jsx)(InputDate_component_1.InputDateComponent, { name: `${name}_${pos}`, value: currentValue || "", onChange: handle, placeholder: pos === "from" ? l.base.filterFrom ? l.base.filterFrom() : "Dari" : l.base.filterTo ? l.base.filterTo() : "Sampai", className: className }));
132
135
  default:
133
- return ((0, jsx_runtime_1.jsx)(Input_component_1.InputComponent, { name: `${name}_${pos}`, value: currentValue || "", onChange: (e) => handle(e.target.value), placeholder: pos === "from" ? "Dari" : "Sampai", className: className }));
136
+ return ((0, jsx_runtime_1.jsx)(Input_component_1.InputComponent, { name: `${name}_${pos}`, value: currentValue || "", onChange: (e) => handle(e.target.value), placeholder: pos === "from" ? l.base.filterFrom ? l.base.filterFrom() : "Dari" : l.base.filterTo ? l.base.filterTo() : "Sampai", className: className }));
134
137
  }
135
138
  };
136
139
  return ((0, jsx_runtime_1.jsxs)("div", { className: "filter-between-container", children: [renderInput("from"), (0, jsx_runtime_1.jsx)("span", { children: "s/d" }), renderInput("to")] }));
@@ -11,7 +11,9 @@ const Pagination_component_1 = require("./Pagination.component");
11
11
  const ScrollContainer_component_1 = require("../wrap/ScrollContainer.component");
12
12
  const Checkbox_component_1 = require("../input/Checkbox.component");
13
13
  const Swipe_component_1 = require("../wrap/Swipe.component");
14
+ const skalfa_lang_1 = require("@skalfa/skalfa-lang");
14
15
  function TableComponent({ id, controlBar, columns, data, pagination, loading, sortBy, onChangeSortBy, search, onChangeSearch, searchableColumn, onChangeSearchableColumn, filter, onChangeFilter, checks, onChangeChecks, actionBulking, focus, onRowClick, onRefresh, block, noIndex, responsiveControl, className = "", }) {
16
+ const l = (0, skalfa_lang_1.useLang)();
15
17
  const [displayColumns, setDisplayColumns] = (0, react_1.useState)([]);
16
18
  const [showFloatingAction, setShowFloatingAction] = (0, react_1.useState)(false);
17
19
  const [floatingActionActive, setFloatingActionActive] = (0, react_1.useState)(false);
@@ -98,10 +100,10 @@ function TableComponent({ id, controlBar, columns, data, pagination, loading, so
98
100
  })), onFilter: (filters) => onChangeFilter?.(filters), filter: filter, className: (0, _utils_1.pcn)(className, "controller-bar") || "" })), (0, jsx_runtime_1.jsx)("div", { className: "relative", children: (0, jsx_runtime_1.jsx)(ScrollContainer_component_1.ScrollContainerComponent, { scrollFloating: !isSm && block, className: "w-full", onScroll: (e) => {
99
101
  actionColumnRef.current?.clientWidth && e.scrollLeft &&
100
102
  setShowFloatingAction(e.scrollLeft + e.clientWidth <= e.scrollWidth - actionColumnRef.current?.clientWidth);
101
- }, footer: (0, jsx_runtime_1.jsx)(jsx_runtime_1.Fragment, { children: block && pagination && ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsx)("div", { className: "py-6" }), (0, jsx_runtime_1.jsx)("div", { className: "my-2 absolute bottom-0 w-full", children: (0, jsx_runtime_1.jsx)(Pagination_component_1.PaginationComponent, { ...pagination }) })] })) }), children: loading ? ((0, jsx_runtime_1.jsx)("div", { className: "w-max min-w-full", children: (0, jsx_runtime_1.jsx)("div", { className: "table-loading-container", children: (0, jsx_runtime_1.jsx)("h1", { className: "table-loading-text", children: "Memuat data..." }) }) })) : !data || !data.length ? ((0, jsx_runtime_1.jsx)("div", { className: "table-empty-container", children: (0, jsx_runtime_1.jsx)("h1", { className: "table-empty-text", children: "Belum Ada Data" }) })) : ((0, jsx_runtime_1.jsx)(jsx_runtime_1.Fragment, { children: !isSm || !responsiveControl?.mobile ? ((0, jsx_runtime_1.jsxs)("div", { className: "w-max min-w-full", children: [(0, jsx_runtime_1.jsxs)("div", { className: (0, _utils_1.cn)("table-head-row", (0, _utils_1.pcn)(className, "row")), children: [!!actionBulking && ((0, jsx_runtime_1.jsx)("div", { className: "table-head-column w-max", children: (0, jsx_runtime_1.jsx)(Checkbox_component_1.CheckboxComponent, { name: "selected_table", className: "w-5 h-5", checked: data.length > 0 && checks?.length === data.length, onChange: () => data.length > 0 && checks?.length === data.length ? onChangeChecks?.([]) : onChangeChecks?.(data.map((d) => d.id)) }) })), !noIndex && (0, jsx_runtime_1.jsx)("div", { className: (0, _utils_1.cn)("table-head-column w-8", (0, _utils_1.pcn)(className, "head-column")), children: "#" }), renderHead()] }), (0, jsx_runtime_1.jsx)("div", { className: "table-body", children: data.map((item, key) => {
103
+ }, footer: (0, jsx_runtime_1.jsx)(jsx_runtime_1.Fragment, { children: block && pagination && ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsx)("div", { className: "py-6" }), (0, jsx_runtime_1.jsx)("div", { className: "my-2 absolute bottom-0 w-full", children: (0, jsx_runtime_1.jsx)(Pagination_component_1.PaginationComponent, { ...pagination }) })] })) }), children: loading ? ((0, jsx_runtime_1.jsx)("div", { className: "w-max min-w-full", children: (0, jsx_runtime_1.jsx)("div", { className: "table-loading-container", children: (0, jsx_runtime_1.jsx)("h1", { className: "table-loading-text", children: l.base.tableLoading ? l.base.tableLoading() : "" }) }) })) : !data || !data.length ? ((0, jsx_runtime_1.jsx)("div", { className: "table-empty-container", children: (0, jsx_runtime_1.jsx)("h1", { className: "table-empty-text", children: l.base.tableEmpty ? l.base.tableEmpty() : "Data empty" }) })) : ((0, jsx_runtime_1.jsx)(jsx_runtime_1.Fragment, { children: !isSm || !responsiveControl?.mobile ? ((0, jsx_runtime_1.jsxs)("div", { className: "w-max min-w-full", children: [(0, jsx_runtime_1.jsxs)("div", { className: (0, _utils_1.cn)("table-head-row", (0, _utils_1.pcn)(className, "row")), children: [!!actionBulking && ((0, jsx_runtime_1.jsx)("div", { className: "table-head-column w-max", children: (0, jsx_runtime_1.jsx)(Checkbox_component_1.CheckboxComponent, { name: "selected_table", className: "w-5 h-5", checked: data.length > 0 && checks?.length === data.length, onChange: () => data.length > 0 && checks?.length === data.length ? onChangeChecks?.([]) : onChangeChecks?.(data.map((d) => d.id)) }) })), !noIndex && (0, jsx_runtime_1.jsx)("div", { className: (0, _utils_1.cn)("table-head-column w-8", (0, _utils_1.pcn)(className, "head-column")), children: "#" }), renderHead()] }), (0, jsx_runtime_1.jsx)("div", { className: "table-body", children: data.map((item, key) => {
102
104
  return ((0, jsx_runtime_1.jsxs)("div", { style: { animationDelay: `${(key + 1) * 0.05}s` }, className: (0, _utils_1.cn)("table-body-row", key % 2 ? "bg-light-primary/10" : "bg-white", focus == key && "bg-light-primary/30", (0, _utils_1.pcn)(className, "row")), children: [!!actionBulking && ((0, jsx_runtime_1.jsx)("div", { className: (0, _utils_1.cn)("table-body-column w-max", (0, _utils_1.pcn)(className, "column")), children: (0, jsx_runtime_1.jsx)(Checkbox_component_1.CheckboxComponent, { name: "selected_table", className: "w-5 h-5", checked: checks?.includes(item?.id), onChange: () => checks?.includes(item?.id) ? onChangeChecks?.(checks.filter((i) => i !== item?.id)) : onChangeChecks?.([...(checks || []), item?.id]) }) })), !noIndex && (0, jsx_runtime_1.jsx)("div", { className: (0, _utils_1.cn)("table-body-column w-8", (0, _utils_1.pcn)(className, "column")), children: numberOfRow(key) }), renderItem(item, key), (0, jsx_runtime_1.jsx)("div", { ref: actionColumnRef, className: "table-action-column", children: item["action"] }), item["action"] && showFloatingAction && ((0, jsx_runtime_1.jsxs)("div", { className: (0, _utils_1.cn)("table-floating-action", (0, _utils_1.pcn)(className, "floating-action")), onClick: () => floatingActionActive !== false &&
103
105
  floatingActionActive == key ? setFloatingActionActive(false) : setFloatingActionActive(key), children: [(0, jsx_runtime_1.jsx)("div", { className: "table-floating-action-icon-wrapper", children: (0, jsx_runtime_1.jsx)(skalfa_icon_1.Icon, { icon: floatingActionActive === false || floatingActionActive != key ? "solid/chevron-left" : "solid/chevron-right" }) }), (0, jsx_runtime_1.jsx)("div", { className: (0, _utils_1.cn)("table-floating-action-content", floatingActionActive === key && "table-floating-action-content-active"), children: item["action"] })] }))] }, key));
104
106
  }) })] })) : ((0, jsx_runtime_1.jsx)("div", { className: "table-mobile-list", children: data.map((item, key) => {
105
107
  return ((0, jsx_runtime_1.jsx)("div", { style: { animationDelay: `${(key + 1) * 0.05}s` }, children: renderItem(item, key) }, key));
106
- }) })) })) }) }), !!actionBulking && !!checks?.length && ((0, jsx_runtime_1.jsxs)("div", { className: "table-bulk-actions-bar", children: [(0, jsx_runtime_1.jsxs)("div", { className: "table-bulk-actions-title", children: [checks?.length, " Data Terpilih"] }), (0, jsx_runtime_1.jsx)("div", { className: "table-bulk-actions-buttons", children: actionBulking?.(checks) })] })), !block && pagination && ((0, jsx_runtime_1.jsx)("div", { className: "table-pagination-desktop", children: (0, jsx_runtime_1.jsx)(Pagination_component_1.PaginationComponent, { ...pagination }) })), pagination && ((0, jsx_runtime_1.jsx)("div", { className: "table-pagination-mobile", children: (0, jsx_runtime_1.jsx)(Pagination_component_1.PaginationComponent, { ...pagination }) }))] }));
108
+ }) })) })) }) }), !!actionBulking && !!checks?.length && ((0, jsx_runtime_1.jsxs)("div", { className: "table-bulk-actions-bar", children: [(0, jsx_runtime_1.jsxs)("div", { className: "table-bulk-actions-title", children: [checks?.length, " ", l.base.tableSelected ? l.base.tableSelected() : ""] }), (0, jsx_runtime_1.jsx)("div", { className: "table-bulk-actions-buttons", children: actionBulking?.(checks) })] })), !block && pagination && ((0, jsx_runtime_1.jsx)("div", { className: "table-pagination-desktop", children: (0, jsx_runtime_1.jsx)(Pagination_component_1.PaginationComponent, { ...pagination }) })), pagination && ((0, jsx_runtime_1.jsx)("div", { className: "table-pagination-mobile", children: (0, jsx_runtime_1.jsx)(Pagination_component_1.PaginationComponent, { ...pagination }) }))] }));
107
109
  }
@@ -7,7 +7,9 @@ const react_1 = require("react");
7
7
  const _utils_1 = require("@utils");
8
8
  const _contexts_1 = require("@contexts");
9
9
  const Modal_component_1 = require("../modal/Modal.component");
10
+ const skalfa_lang_1 = require("@skalfa/skalfa-lang");
10
11
  function ShortcutProvider() {
12
+ const l = (0, skalfa_lang_1.useLang)();
11
13
  const { setToggle, toggle } = (0, _contexts_1.useToggleContext)();
12
14
  const shortcuts = _utils_1.shortcut.list();
13
15
  (0, react_1.useEffect)(() => {
@@ -16,7 +18,7 @@ function ShortcutProvider() {
16
18
  (0, react_1.useEffect)(() => {
17
19
  _utils_1.shortcut.register("ctrl+/", () => {
18
20
  setToggle("MODAL_SHORTCUT_HELP");
19
- }, "List Shortcut");
21
+ }, l.base.shortcutList ? l.base.shortcutList() : "");
20
22
  }, []);
21
23
  function formatShortcutKey(key) {
22
24
  return key
@@ -38,5 +40,5 @@ function ShortcutProvider() {
38
40
  })
39
41
  .join(" + ");
40
42
  }
41
- return ((0, jsx_runtime_1.jsx)(jsx_runtime_1.Fragment, { children: (0, jsx_runtime_1.jsx)(Modal_component_1.ModalComponent, { show: !!toggle["MODAL_SHORTCUT_HELP"], onClose: () => setToggle("MODAL_SHORTCUT_HELP"), title: "Shortcut", children: (0, jsx_runtime_1.jsx)("div", { className: "shortcut-help-grid", children: shortcuts.map(({ key, description }) => ((0, jsx_runtime_1.jsxs)(react_1.Fragment, { children: [(0, jsx_runtime_1.jsx)("kbd", { className: "shortcut-key-badge", children: formatShortcutKey(key) }), (0, jsx_runtime_1.jsxs)("span", { children: [": ", description] })] }, key))) }) }) }));
43
+ return ((0, jsx_runtime_1.jsx)(jsx_runtime_1.Fragment, { children: (0, jsx_runtime_1.jsx)(Modal_component_1.ModalComponent, { show: !!toggle["MODAL_SHORTCUT_HELP"], onClose: () => setToggle("MODAL_SHORTCUT_HELP"), title: l.base.shortcut ? l.base.shortcut() : "", children: (0, jsx_runtime_1.jsx)("div", { className: "shortcut-help-grid", children: shortcuts.map(({ key, description }) => ((0, jsx_runtime_1.jsxs)(react_1.Fragment, { children: [(0, jsx_runtime_1.jsx)("kbd", { className: "shortcut-key-badge", children: formatShortcutKey(key) }), (0, jsx_runtime_1.jsxs)("span", { children: [": ", description] })] }, key))) }) }) }));
42
44
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@skalfa/skalfa-component",
3
- "version": "1.0.10",
3
+ "version": "1.0.11",
4
4
  "description": "Reusable UI components for Skalfa App.",
5
5
  "license": "MIT",
6
6
  "keywords": [
@@ -4,6 +4,7 @@ import { ReactNode, useEffect, useMemo, useState } from "react";
4
4
  import { api, ApiType, cn, pcn, registry, shortcut, useResponsive } from "@utils";
5
5
  import { ButtonComponent, ButtonProps, BottomSheetComponent } from "@components";
6
6
  import { Icon } from "@skalfa/skalfa-icon";
7
+ import { useLang } from "@skalfa/skalfa-lang";
7
8
 
8
9
 
9
10
 
@@ -41,6 +42,7 @@ export function ModalConfirmComponent({
41
42
 
42
43
  className = "",
43
44
  }: ModalConfirmProps) {
45
+ const l = useLang()
44
46
  const { isSm } = useResponsive();
45
47
  const [toast, setToast] = useState<boolean | "success" | "failed">(false);
46
48
  const [loading, setLoading] = useState(false);
@@ -69,7 +71,7 @@ export function ModalConfirmComponent({
69
71
  <div className="w-12 h-12 rounded-full bg-blue-50 flex items-center justify-center">
70
72
  <Icon icon={"solid/check"} className="text-primary text-2xl" />
71
73
  </div>
72
- <p className="text-primary text-lg font-semibold mt-4">{"Berhasil!"}</p>
74
+ <p className="text-primary text-lg font-semibold mt-4">{l.base.success ? l.base.success() : "Success"}</p>
73
75
  </div>
74
76
  )
75
77
  }
@@ -97,7 +99,7 @@ export function ModalConfirmComponent({
97
99
  <Icon icon={"solid/exclamation-triangle"} className="text-danger text-lg" />
98
100
  </div>
99
101
  </div>
100
- <p className="text-danger text-sm font-semibold">{"Terjadi Masalah, Coba ulangi lagi!"}</p>
102
+ <p className="text-danger text-sm font-semibold">{l.base.confirmFailed ? l.base.confirmFailed() : "Failed"}</p>
101
103
  </div>
102
104
  </div>
103
105
  )}
@@ -112,14 +114,14 @@ export function ModalConfirmComponent({
112
114
  return (
113
115
  <div className="flex justify-center gap-4 p-6 pt-2">
114
116
  <ButtonComponent
115
- label="Batal"
117
+ label={l.base.cancel ? l.base.cancel() : ""}
116
118
  variant="outline"
117
119
  onClick={() => onClose()}
118
120
  block
119
121
  size={size}
120
122
  />
121
123
  <ButtonComponent
122
- label={"Konfirmasi"}
124
+ label={l.base.confirm ? l.base.confirm() : ""}
123
125
  loading={loading}
124
126
  onClick={async () => {
125
127
  if(!submitControl?.onSubmit) return;
@@ -69,15 +69,15 @@ const defaultColumns: FooterColumnProps[] = [
69
69
  ];
70
70
 
71
71
  export function FooterComponent({
72
- brandTitle = "Next Light v.3",
73
- brandSubtitle = "The Magic Starter Template",
74
- address = { label: "Soekarno Hatta No 27 C, Ponorogo, Jawa Timur, Indonesia", path: "https://maps.app.goo.gl/TY2QDjFPm3RfwjUq6" },
75
- phone = { label: "+62 888888888888", path: "https://wa.me/6281456140392" },
76
- email = { label: "example@gmail.com", path: "mailto:sejedigital@gmail.com" },
77
- supportHours = "24 / 7 Online Suport | Senin - Sabtu ( 09.00 s/d 17.00 )",
78
- socials = defaultSocials,
79
- columns = defaultColumns,
80
- copyrightLink = { label: "sejedigital.com 2020 - 2025", path: "https://sejedigital.com/" },
72
+ brandTitle = "Next Light v.3",
73
+ brandSubtitle = "The Magic Starter Template",
74
+ address = { label: "Soekarno Hatta No 27 C, Ponorogo, Jawa Timur, Indonesia", path: "https://maps.app.goo.gl/TY2QDjFPm3RfwjUq6" },
75
+ phone = { label: "+62 888888888888", path: "https://wa.me/6281456140392" },
76
+ email = { label: "example@gmail.com", path: "mailto:sejedigital@gmail.com" },
77
+ supportHours = "24 / 7 Online Suport | Senin - Sabtu ( 09.00 s/d 17.00 )",
78
+ socials = defaultSocials,
79
+ columns = defaultColumns,
80
+ copyrightLink = { label: "sejedigital.com 2020 - 2025", path: "https://sejedigital.com/" },
81
81
  }: FooterProps) {
82
82
  return (
83
83
  <>
@@ -37,12 +37,12 @@ const defaultSpecialLink = {
37
37
  } as const;
38
38
 
39
39
  export function NavbarComponent({
40
- logoTitle = "Next Light v.3",
41
- logoSubtitle = "The Magic Starter Template",
42
- logoPath = "/",
43
- specialLink = defaultSpecialLink,
44
- items = defaultItems,
45
- isLoggedIn = false,
40
+ logoTitle = "Next Light v.3",
41
+ logoSubtitle = "The Magic Starter Template",
42
+ logoPath = "/",
43
+ specialLink = defaultSpecialLink,
44
+ items = defaultItems,
45
+ isLoggedIn = false,
46
46
  onLogin,
47
47
  onRegister,
48
48
  onProfile,
@@ -41,9 +41,7 @@ export function TabbarComponent({
41
41
  key={i}
42
42
  className={cn(
43
43
  "tabbar-item",
44
- isItemActive
45
- ? "tabbar-item-active"
46
- : "tabbar-item-inactive",
44
+ isItemActive ? "tabbar-item-active" : "tabbar-item-inactive",
47
45
  pcn<CT>(className, "item"),
48
46
  pcn<CT>(className, "active"),
49
47
  )}
@@ -301,7 +301,7 @@ export function FormSupervisionComponent({
301
301
  <div>
302
302
  <ButtonComponent
303
303
  icon={"solid/plus"}
304
- label={`Tambah ${label || mapName}`}
304
+ label={`${l.base.add ? l.base.add() : "Add"} ${label || mapName}`}
305
305
  variant="outline"
306
306
  size="sm"
307
307
  onClick={addGroup}
@@ -332,6 +332,10 @@ export function FormSupervisionComponent({
332
332
  );
333
333
  };
334
334
 
335
+ useEffect(() => {
336
+ setModal(false)
337
+ }, [values]);
338
+
335
339
  return (
336
340
  <>
337
341
  {title && <h4 className={cn("text-lg font-semibold mb-4", pcn<CT>(className, "title"))}>{title}</h4>}
@@ -341,7 +345,7 @@ export function FormSupervisionComponent({
341
345
  <div className="w-12 h-12 rounded-full bg-blue-50 flex items-center justify-center">
342
346
  <Icon icon={"solid/check"} className="text-primary text-2xl" />
343
347
  </div>
344
- <p className="text-primary text-lg font-semibold mt-4">{successMessage || "Berhasil disimpan!"}</p>
348
+ <p className="text-primary text-lg font-semibold mt-4">{successMessage || l.base?.success ? l.base.success() : "Success!"}</p>
345
349
  </div>
346
350
  ) : (
347
351
  <form id={id} className={cn("flex flex-col h-full pb-8")} onSubmit={submit}>
@@ -386,7 +390,7 @@ export function FormSupervisionComponent({
386
390
  <Icon icon={"solid/exclamation-triangle"} className="text-danger text-lg" />
387
391
  </div>
388
392
  </div>
389
- <p className="text-danger text-sm font-semibold">{"Terjadi Masalah, Coba ulangi lagi!"}</p>
393
+ <p className="text-danger text-sm font-semibold">{l.base.formFailed ? l.base.formFailed() : "Failed to save data, please check your data and internet connection then try again!"}</p>
390
394
  </div>
391
395
  )}
392
396
  </div>
@@ -396,7 +400,7 @@ export function FormSupervisionComponent({
396
400
  <ModalConfirmComponent
397
401
  show={confirm.show}
398
402
  onClose={() => confirm.onClose()}
399
- title={l.base?.confirmTitle ? l.base.confirmTitle() : "Yakin"}
403
+ title={l.base?.formConfirm ? l.base.formConfirm() : "Are you sure all data is correct?"}
400
404
  submitControl={{ onSubmit: () => confirm?.onConfirm(), paint: "primary" }}
401
405
  />
402
406
  </>
@@ -112,31 +112,31 @@ export function TableSupervisionComponent({
112
112
  shortcut.register("arrowdown", () => {
113
113
  const max = data?.data?.length - 1;
114
114
  setFocus(focus == null ? 0 : focus >= max ? max : (focus + 1))
115
- }, "Pilih data kebawah")
115
+ }, l.base.shortcutDown ? l.base.shortcutDown() : "")
116
116
 
117
117
  shortcut.register("arrowup", () => {
118
118
  setFocus(focus == null ? 0 : focus <= 0 ? 0 : (focus - 1))
119
- }, "Pilih data keatas")
119
+ }, l.base.shortcutUp ? l.base.shortcutUp() : "")
120
120
 
121
121
  if(focus != null) {
122
122
  shortcut.register("delete", () => {
123
123
  setSelected(data?.data?.at(focus))
124
124
  setToggle(`MODAL_DELETE_${toggleKey}`)
125
- }, "Delete data yang dipilih")
125
+ }, l.base.shortcutDelete ? l.base.shortcutDelete() : "")
126
126
 
127
127
  shortcut.register(" ", () => {
128
128
  setSelected(data?.data?.at(focus))
129
129
  setToggle(`MODAL_FORM_${toggleKey}`)
130
- }, "Edit data yang dipilih")
130
+ }, l.base.shortcutEdit ? l.base.shortcutEdit() : "")
131
131
 
132
132
  shortcut.register("enter", () => {
133
133
  setSelected(data?.data?.at(focus))
134
134
  setToggle(`MODAL_SHOW_${toggleKey}`)
135
- }, "Detail data yang dipilih")
135
+ }, l.base.shortcutDetail ? l.base.shortcutDetail() : "")
136
136
 
137
137
  shortcut.register("escape", () => {
138
138
  setFocus(null)
139
- }, "Kembali")
139
+ }, l.base.shortcutBack ? l.base.shortcutBack() : "")
140
140
  }
141
141
  }
142
142
 
@@ -339,9 +339,9 @@ export function TableSupervisionComponent({
339
339
  col : 12,
340
340
  type : "text",
341
341
  construction : {
342
- name : typeof col == "string" ? col : col?.selector,
343
- label : typeof col == "string" ? col : col?.label,
344
- placeholder : `Masukkan ${ typeof col == "string" ? col : col?.label}...`,
342
+ name : typeof col == "string" ? col : col?.selector,
343
+ label : typeof col == "string" ? col : col?.label,
344
+ placeholder : l.base.inputPlaceholder ? l.base.inputPlaceholder(`${ typeof col == "string" ? col : col?.label}`) : `Enter ${ typeof col == "string" ? col : col?.label}...`,
345
345
  },
346
346
  };
347
347
  }) || (data?.data?.at(0) ? Object.keys(data.data[0]).map((col) => {
@@ -351,7 +351,7 @@ export function TableSupervisionComponent({
351
351
  construction : {
352
352
  name : col,
353
353
  label : col,
354
- placeholder : `Masukkan ${col}...`,
354
+ placeholder : l.base.inputPlaceholder ? l.base.inputPlaceholder(col) : `Enter ${col}...`,
355
355
  },
356
356
  };
357
357
  })
@@ -367,12 +367,12 @@ export function TableSupervisionComponent({
367
367
  return (
368
368
  <FormSupervisionComponent
369
369
  submitControl={(fetchControl as ApiType).path ? {
370
- path: `${(fetchControl as ApiType).path}/${(selected as { id: number })?.id || "" }`,
371
- method: !(selected as { id: number })?.id ? "POST" : "PUT",
372
- } : (fetchControl as ApiType).url ? {
373
- url: `${(fetchControl as ApiType).url}/${(selected as { id: number })?.id || ""}`,
374
- method: !(selected as { id: number })?.id ? "POST" : "PUT",
375
- } : { idb: (fetchControl as ({ idb: UseResourceIdb }))?.idb }
370
+ path : `${(fetchControl as ApiType).path}/${(selected as { id: number })?.id || "" }`,
371
+ method : !(selected as { id: number })?.id ? "POST" : "PUT",
372
+ } : (fetchControl as ApiType).url ? {
373
+ url : `${(fetchControl as ApiType).url}/${(selected as { id: number })?.id || ""}`,
374
+ method : !(selected as { id: number })?.id ? "POST" : "PUT",
375
+ } : { idb: (fetchControl as ({ idb: UseResourceIdb }))?.idb }
376
376
  }
377
377
  fields={fields?.filter((f: any) => f.visibility ? !(selected as { id: number })?.id ? ["*", "create"]?.includes(f.visibility) : ["*", "update"]?.includes(f.visibility) : true) as FormType[]}
378
378
  defaultValue={formControl?.defaultValue ? await formControl?.defaultValue(selected || null) : selected}
@@ -401,11 +401,12 @@ export function TableSupervisionComponent({
401
401
  controlBar={controlBar?.map((cb) => {
402
402
  if (cb == "CREATE") {
403
403
  if (isSm) return
404
+
404
405
  return (
405
406
  <div className="pl-1.5 pr-3 mr-2 border-r" key="button-add">
406
407
  <ButtonComponent
407
408
  icon={"solid/plus"}
408
- label="Tambah Data"
409
+ label={l.base.add ? l.base.add() : "Add"}
409
410
  size="sm"
410
411
  onClick={() => {
411
412
  setToggle(`MODAL_FORM_${toggleKey}`)
@@ -421,7 +422,6 @@ export function TableSupervisionComponent({
421
422
  <div className="px-1.5 rounded-md relative" key={"import"}>
422
423
  <ButtonComponent
423
424
  icon={"solid/file-excel"}
424
- label="Import"
425
425
  variant="outline"
426
426
  className="!text-foreground"
427
427
  onClick={() => setToggle(`MODAL_IMPORT_${toggleKey}`)}
@@ -436,7 +436,6 @@ export function TableSupervisionComponent({
436
436
  <div className="px-1.5 rounded-md relative" key={"export-excel"}>
437
437
  <ButtonComponent
438
438
  icon={"solid/file-excel"}
439
- label="Export"
440
439
  variant="outline"
441
440
  className="!text-foreground"
442
441
  onClick={() => setToggle(`MODAL_EXPORT_${toggleKey}`)}
@@ -451,7 +450,7 @@ export function TableSupervisionComponent({
451
450
  <div className="px-1.5 rounded-md relative" key={"export-pdf"}>
452
451
  <ButtonComponent
453
452
  icon={"solid/file-pdf"}
454
- label="Cetak"
453
+ label={l.base.print ? l.base.print() : "Print"}
455
454
  variant="outline"
456
455
  className="!text-foreground"
457
456
  onClick={() => setToggle(`MODAL_PRINT_${toggleKey}`)}
@@ -467,7 +466,7 @@ export function TableSupervisionComponent({
467
466
  <div className="pl-1.5 pr-3 mr-2 border-r" key="button-add">
468
467
  <ButtonComponent
469
468
  icon={"solid/plus"}
470
- label="Tambah Data"
469
+ label={l.base.add ? l.base.add() : "Add"}
471
470
  size="sm"
472
471
  onClick={() => {
473
472
  setToggle(`MODAL_FORM_${toggleKey}`)
@@ -532,7 +531,7 @@ export function TableSupervisionComponent({
532
531
  <FloatingPageComponent
533
532
  show={!!toggle[`MODAL_SHOW_${toggleKey}`]}
534
533
  onClose={() => setToggle(`MODAL_SHOW_${toggleKey}`, false)}
535
- title="Detail"
534
+ title={l.base.detailTitle ? l.base.detailTitle() : "Detail"}
536
535
  className="bg-background"
537
536
  footer={renderTableAction(actionControl, undefined, {className: isSm ? "justify-end p-2 bg-background" : "justify-end", size: isSm ? "sm" : "md"})}
538
537
  >
@@ -543,7 +542,7 @@ export function TableSupervisionComponent({
543
542
  <FloatingPageComponent
544
543
  show={!!toggle[`MODAL_FORM_${toggleKey}`]}
545
544
  onClose={() => setToggle(`MODAL_FORM_${toggleKey}`, false)}
546
- title={!!selected ? "Ubah Data" : "Tambah Data"}
545
+ title={!!selected ? (l.base.editTitle ? l.base.editTitle() : "Edit") : (l.base.addTitle ? l.base.addTitle() : "Add")}
547
546
  className={cn("bg-white", formControl?.modalControl?.className)}
548
547
  >
549
548
  <div className="p-4">
@@ -555,12 +554,12 @@ export function TableSupervisionComponent({
555
554
  <FloatingPageComponent
556
555
  show={!!toggle[`MODAL_EXPORT_${toggleKey}`]}
557
556
  onClose={() => setToggle(`MODAL_EXPORT_${toggleKey}`, false)}
558
- title="Export Ke Excel"
557
+ title={l.base.exportTitle ? l.base.exportTitle() : "Export"}
559
558
  className="bg-white md:w-[1200px] max-w-[1200px]"
560
559
  >
561
560
  <ExportExcel
562
561
  fetchControl={fetchControl}
563
- filename={"Export - " + title}
562
+ filename={"export"}
564
563
  columnControl={columns?.map((cc) => ({
565
564
  label: cc.label || "",
566
565
  selector: cc.selector || "",
@@ -572,7 +571,7 @@ export function TableSupervisionComponent({
572
571
  <FloatingPageComponent
573
572
  show={!!toggle[`MODAL_IMPORT_${toggleKey}`]}
574
573
  onClose={() => setToggle(`MODAL_IMPORT_${toggleKey}`, false)}
575
- title="Import Dari Excel"
574
+ title={l.base.importTitle ? l.base.importTitle() : "Import"}
576
575
  className="bg-white md:w-[1200px] max-w-[1200px]"
577
576
  >
578
577
  <ImportExcel
@@ -605,7 +604,7 @@ export function TableSupervisionComponent({
605
604
  <ModalConfirmComponent
606
605
  show={!!toggle[`MODAL_DELETE_${toggleKey}`]}
607
606
  onClose={() => setToggle(`MODAL_DELETE_${toggleKey}`, false)}
608
- title={<>Menghapus Data <span className="font-semibold">&quot;{selected?.[columns?.at(0)?.selector || ""]}&quot;</span> ?</>}
607
+ title={l.base.deleteTitle ? l.base.deleteTitle({ data: selected?.[columns?.at(0)?.selector || ""] }) : `Delete ${selected?.[columns?.at(0)?.selector || ""]}?`}
609
608
  submitControl={{
610
609
  onSubmit: {
611
610
  ...((fetchControl as ApiType).path
@@ -1,5 +1,5 @@
1
1
  "use client"
2
- import { Icon, type IconName } from "@skalfa/skalfa-icon";
2
+ import { Icon } from "@skalfa/skalfa-icon";
3
3
 
4
4
 
5
5
  import { ReactNode, useEffect, useRef } from 'react'
@@ -12,6 +12,7 @@ import { OutsideClickComponent } from "../wrap/OutsideClick.component";
12
12
  import { ButtonComponent } from "../button/Button.component";
13
13
  import { BottomSheetComponent } from "../modal/BottomSheet.component";
14
14
  import { FilterComponent, FilterColumnOption } from "./FilterComponent";
15
+ import { useLang } from "@skalfa/skalfa-lang";
15
16
 
16
17
  export type ControlBarOptionType = "SEARCH" | "SEARCHABLE" | "FILTER" | "SELECTABLE" | "REFRESH" | ReactNode;
17
18
 
@@ -56,6 +57,7 @@ export function ControlBarComponent({
56
57
  filter,
57
58
  onRefresh
58
59
  }: ControlBarProps) {
60
+ const l = useLang();
59
61
  const {toggle, setToggle} = useToggleContext()
60
62
  const { isSm } = useResponsive();
61
63
 
@@ -65,31 +67,31 @@ export function ControlBarComponent({
65
67
  if (options?.includes("SEARCH")) {
66
68
  shortcut.register("ctrl+s", () => {
67
69
  searchRef.current?.focus()
68
- }, "Cari")
70
+ }, l.base.shortcutSearch ? l.base.shortcutSearch() : "Search")
69
71
  }
70
72
 
71
73
  if (options?.includes("FILTER")) {
72
74
  shortcut.register("ctrl+f", () => {
73
75
  setToggle("FILTER")
74
- }, "Filter")
76
+ }, l.base.shortcutFilter ? l.base.shortcutFilter() : "Filter")
75
77
  }
76
78
 
77
79
  if (options?.includes("SORT")) {
78
80
  shortcut.register("ctrl+o", () => {
79
81
  setToggle("SORT")
80
- }, "Urutkan")
82
+ }, l.base.shortcutSort ? l.base.shortcutSort() : "Sort")
81
83
  }
82
84
 
83
85
  if (options?.includes("SELECTABLE")) {
84
86
  shortcut.register("ctrl+l", () => {
85
87
  setToggle("SELECTABLE")
86
- }, "Kolom Ditampilkan")
88
+ }, l.base.shortcutSelectable ? l.base.shortcutSelectable() : "Select")
87
89
  }
88
90
 
89
91
  if (options?.includes("REFRESH")) {
90
92
  shortcut.register("ctrl+shift+r", () => {
91
93
  onRefresh?.()
92
- }, "Refresh Tabel")
94
+ }, l.base.shortcutRefresh ? l.base.shortcutRefresh() : "Refresh")
93
95
  }
94
96
 
95
97
  return () => {
@@ -134,7 +136,7 @@ export function ControlBarComponent({
134
136
  <div className="control-bar-create-wrapper" key="button-add">
135
137
  <ButtonComponent
136
138
  icon="solid/plus"
137
- label="Tambah Data"
139
+ label={l.base.add ? l.base.add() : "Add"}
138
140
  size="sm"
139
141
  onClick={() => setToggle(`MODAL_FORM_${conversion.strSnake(id).toUpperCase()}`)}
140
142
  />
@@ -155,7 +157,7 @@ export function ControlBarComponent({
155
157
  <InputComponent
156
158
  ref={searchRef}
157
159
  name="search"
158
- placeholder="Cari disini..."
160
+ placeholder={l.base.searchPlaceholder ? l.base.searchPlaceholder() : "Search here..."}
159
161
  rightIcon="solid/magnifying-glass"
160
162
  value={search}
161
163
  onChange={(e) => onSearch?.(e)}
@@ -213,7 +215,7 @@ export function ControlBarComponent({
213
215
  !toggle.SELECTABLE && "control-bar-dropdown-hidden"
214
216
  )}
215
217
  >
216
- <p className='control-bar-dropdown-title'>Kolom Ditampilkan</p>
218
+ <p className='control-bar-dropdown-title'>{l.base.selectable ? l.base.selectable() : "Show Column"}</p>
217
219
  <InputCheckboxComponent
218
220
  vertical
219
221
  name="show_column"
@@ -256,7 +258,7 @@ export function ControlBarComponent({
256
258
  !toggle.SORT && "control-bar-dropdown-hidden"
257
259
  )}
258
260
  >
259
- <p className='control-bar-dropdown-title'>Urut Berdasarkan</p>
261
+ <p className='control-bar-dropdown-title'>{l.base.sort ? l.base.sort() : "Sort By"}</p>
260
262
  <div className='control-bar-sort-list'>
261
263
  {sortableOptions?.map((option, key) => {
262
264
  const sortBy = sort?.find((s) => s.split(" ")?.at(0) == option?.selector)?.split(" ")?.at(1) || "";
@@ -376,7 +378,7 @@ export function ControlBarComponent({
376
378
  <div key={key}>
377
379
  <InputComponent
378
380
  name="search"
379
- placeholder="Cari disini..."
381
+ placeholder={l.base.searchPlaceholder ? l.base.searchPlaceholder() : "Search here..."}
380
382
  rightIcon="solid/magnifying-glass"
381
383
  value={search}
382
384
  onChange={(e) => onSearch?.(e)}
@@ -418,7 +420,7 @@ export function ControlBarComponent({
418
420
  if (option == "SELECTABLE") {
419
421
  return (
420
422
  <div key={key}>
421
- <p className='control-bar-mobile-title'>Kolom Ditampilkan</p>
423
+ <p className='control-bar-mobile-title'>{l.base.selectable ? l.base.selectable() : "Show Column"}</p>
422
424
  <InputCheckboxComponent
423
425
  vertical
424
426
  name="show_column"
@@ -445,7 +447,7 @@ export function ControlBarComponent({
445
447
  if (option == "SORT") {
446
448
  return sortableOptions?.length ? (
447
449
  <div key={key}>
448
- <p className='control-bar-mobile-title'>Urut Berdasarkan</p>
450
+ <p className='control-bar-mobile-title'>{l.base.sort ? l.base.sort() : "Sort By"}</p>
449
451
  <div className='flex flex-col'>
450
452
  {sortableOptions?.map((option, key) => {
451
453
  const sortBy = sort?.find((s) => s.split(" ")?.at(0) == option?.selector)?.split(" ")?.at(1) || "";
@@ -11,6 +11,7 @@ import { InputNumberComponent } from "../input/InputNumber.component";
11
11
  import { ModalComponent } from "../modal/Modal.component";
12
12
  import { SelectComponent } from "../input/Select.component";
13
13
  import { useToggleContext } from "@contexts";
14
+ import { useLang } from "@skalfa/skalfa-lang";
14
15
 
15
16
  type CT = "base" | "title";
16
17
 
@@ -65,6 +66,8 @@ export function FilterComponent({
65
66
  onMinimize,
66
67
  className = "",
67
68
  }: AdvancedFilterProps) {
69
+ const l = useLang();
70
+
68
71
  const { isSm } = useResponsive();
69
72
  const { toggle, setToggle } = useToggleContext()
70
73
  const [filters, setFilters] = useState<ApiFilterType[]>([]);
@@ -116,7 +119,7 @@ export function FilterComponent({
116
119
  <>
117
120
  <div className={cn("filter-panel", pcn<CT>(className, "base"))}>
118
121
  <div className="filter-panel-header">
119
- <p className={cn(pcn<CT>(className, "title"))}>Filter</p>
122
+ <p className={cn(pcn<CT>(className, "title"))}>{l.base.filter ? l.base.filter() : "Filter"}</p>
120
123
  <div className="filter-panel-controls">
121
124
  <div className="filter-panel-bookmarks-wrapper">
122
125
  <ButtonComponent
@@ -150,7 +153,7 @@ export function FilterComponent({
150
153
 
151
154
  <ButtonComponent
152
155
  icon="solid/rotate"
153
- label="Bersihkan"
156
+ label={l.base.clear ? l.base.clear() : "Filter"}
154
157
  variant="outline"
155
158
  paint="primary"
156
159
  className="filter-panel-bookmark-btn icon::text-slate-400"
@@ -181,7 +184,7 @@ export function FilterComponent({
181
184
  <SelectComponent
182
185
  name={`filter_logic_${i}`}
183
186
  options={LOGIC_OPTIONS}
184
- placeholder="Dan/Atau"
187
+ placeholder={l.base.filterLogic ? l.base.filterLogic() : "And/Or"}
185
188
  value={f.logic}
186
189
  onChange={(e) => handleChange(i, "logic", e as "and" | "or")}
187
190
  className="filter-input-field"
@@ -196,7 +199,7 @@ export function FilterComponent({
196
199
  label: c.label,
197
200
  value: c.selector,
198
201
  }))}
199
- placeholder="Kolom"
202
+ placeholder={l.base.column ? l.base.column() : "Column"}
200
203
  value={f.column}
201
204
  onChange={(e) => handleChange(i, "column", e)}
202
205
  className="filter-input-field"
@@ -207,7 +210,7 @@ export function FilterComponent({
207
210
  <SelectComponent
208
211
  name={`filter_operator_${i}`}
209
212
  options={FILTER_OPERATORS}
210
- placeholder="Operator"
213
+ placeholder={l.base.filterOperator ? l.base.filterOperator() : "Operation"}
211
214
  value={f.type}
212
215
  onChange={(e) => handleChange(i, "type", e)}
213
216
  className="filter-input-field"
@@ -254,7 +257,7 @@ export function FilterComponent({
254
257
  })}
255
258
 
256
259
  <ButtonComponent
257
- label="Tambahkan"
260
+ label={l.base.add ? l.base.add() : "Add"}
258
261
  icon="solid/plus"
259
262
  variant="outline"
260
263
  paint="primary"
@@ -267,7 +270,7 @@ export function FilterComponent({
267
270
  <ModalComponent
268
271
  show={!!toggle["MODAL_BOOKMARK_LIST"]}
269
272
  onClose={() => setToggle("MODAL_BOOKMARK_LIST", false)}
270
- title="Bookmark Filter"
273
+ title={l.base.filterBookmarks ? l.base.filterBookmarks() : "Filter Bookmark"}
271
274
  >
272
275
  <div className="filter-bookmark-list-container">
273
276
  {bookmarks?.length ? bookmarks?.map((b, key) => (
@@ -296,7 +299,7 @@ export function FilterComponent({
296
299
  </div>
297
300
  </div>
298
301
  )) : (
299
- <div className="filter-bookmark-empty-text"> -- Tidak ada Bookmark --</div>
302
+ <div className="filter-bookmark-empty-text"> -- {l.base.filterBookmarkEmpty ? l.base.filterBookmarkEmpty() : "No Bookmark"} --</div>
300
303
  )}
301
304
  </div>
302
305
  </ModalComponent>
@@ -304,11 +307,11 @@ export function FilterComponent({
304
307
  <ModalComponent
305
308
  show={!!toggle["MODAL_BOOKMARK"]}
306
309
  onClose={() => setToggle("MODAL_BOOKMARK", false)}
307
- title="Bookmark Filter"
310
+ title={l.base.filterBookmark ? l.base.filterBookmark() : "Filter Bookmark"}
308
311
  footer={
309
312
  <div className="flex justify-end">
310
313
  <ButtonComponent
311
- label="Terapkan"
314
+ label={l.base.apply ? l.base.apply() : "Apply"}
312
315
  onClick={() => {
313
316
  let updated: FilterBookmark[] = [];
314
317
 
@@ -339,12 +342,12 @@ export function FilterComponent({
339
342
  <div className="filter-bookmark-form-container">
340
343
  <SelectComponent
341
344
  name={`bookmark_id`}
342
- placeholder="Pilih bookmark filter..."
345
+ placeholder={l.base.filterBookmarkPlaceholder ? l.base.filterBookmarkPlaceholder() : "Pilih bookmark filter..."}
343
346
  value={(toggle["MODAL_BOOKMARK"] as { bookmark_id: string })?.bookmark_id ?? ""}
344
347
  onChange={e => setToggle("MODAL_BOOKMARK", {...(toggle["MODAL_BOOKMARK"] as object), bookmark_id: e})}
345
348
  options={[
346
349
  {
347
- label: "-- BOOKMARK BARU --",
350
+ label: `-- ${l.base.filterBookmarkNew ? l.base.filterBookmarkNew() : "New Filter Bookmark"} --`,
348
351
  value: "new",
349
352
  },
350
353
  ...bookmarks.map((b) => ({
@@ -357,7 +360,7 @@ export function FilterComponent({
357
360
  {(toggle["MODAL_BOOKMARK"] as { bookmark_id: string })?.bookmark_id == "new" && (
358
361
  <InputComponent
359
362
  name="bookmark_name"
360
- placeholder="Masukkan nama bookmark..."
363
+ placeholder={l.base.filterBookmarkNewPlaceholder ? l.base.filterBookmarkNewPlaceholder() : "Masukkan nama bookmark..."}
361
364
  value={(toggle["MODAL_BOOKMARK"] as { bookmark_name: string })?.bookmark_name ?? ""}
362
365
  onChange={e => setToggle("MODAL_BOOKMARK", {...(toggle["MODAL_BOOKMARK"] as object), bookmark_name: e})}
363
366
  className="filter-bookmark-form-input"
@@ -392,6 +395,8 @@ export function InputFilterValueComponent({
392
395
  between,
393
396
  multiple,
394
397
  }: FilterInputProps) {
398
+ const l = useLang();
399
+
395
400
  const resolvedType = type || "text";
396
401
 
397
402
  if (!between) {
@@ -470,7 +475,7 @@ export function InputFilterValueComponent({
470
475
  name={`${name}_${pos}`}
471
476
  value={Number(currentValue) || 0}
472
477
  onChange={handle}
473
- placeholder={pos === "from" ? "Dari" : "Sampai"}
478
+ placeholder={pos === "from" ? l.base.filterFrom ? l.base.filterFrom() : "Dari" : l.base.filterTo ? l.base.filterTo() : "Sampai"}
474
479
  className={className}
475
480
  />
476
481
  );
@@ -480,7 +485,7 @@ export function InputFilterValueComponent({
480
485
  name={`${name}_${pos}`}
481
486
  value={Number(currentValue) || 0}
482
487
  onChange={handle}
483
- placeholder={pos === "from" ? "Dari" : "Sampai"}
488
+ placeholder={pos === "from" ? l.base.filterFrom ? l.base.filterFrom() : "Dari" : l.base.filterTo ? l.base.filterTo() : "Sampai"}
484
489
  className={className}
485
490
  />
486
491
  );
@@ -490,7 +495,7 @@ export function InputFilterValueComponent({
490
495
  name={`${name}_${pos}`}
491
496
  value={currentValue as string || ""}
492
497
  onChange={handle}
493
- placeholder={pos === "from" ? "Dari" : "Sampai"}
498
+ placeholder={pos === "from" ? l.base.filterFrom ? l.base.filterFrom() : "Dari" : l.base.filterTo ? l.base.filterTo() : "Sampai"}
494
499
  className={className}
495
500
  />
496
501
  );
@@ -500,7 +505,7 @@ export function InputFilterValueComponent({
500
505
  name={`${name}_${pos}`}
501
506
  value={currentValue || ""}
502
507
  onChange={(e: any) => handle(e.target.value)}
503
- placeholder={pos === "from" ? "Dari" : "Sampai"}
508
+ placeholder={pos === "from" ? l.base.filterFrom ? l.base.filterFrom() : "Dari" : l.base.filterTo ? l.base.filterTo() : "Sampai"}
504
509
  className={className}
505
510
  />
506
511
  );
@@ -10,6 +10,7 @@ import { ScrollContainerComponent } from "../wrap/ScrollContainer.component";
10
10
  import { FilterColumnOption } from "./FilterComponent";
11
11
  import { CheckboxComponent } from "../input/Checkbox.component";
12
12
  import { SwipeComponent, SwipeActionType } from "../wrap/Swipe.component";
13
+ import { useLang } from "@skalfa/skalfa-lang";
13
14
 
14
15
  type CT = "controller-bar" | "head-column" | "column" | "row" | "floating-action" | "base";
15
16
 
@@ -102,6 +103,8 @@ export function TableComponent({
102
103
 
103
104
  className = "",
104
105
  }: TableProps) {
106
+ const l = useLang();
107
+
105
108
  const [displayColumns, setDisplayColumns] = useState<string[]>([]);
106
109
  const [showFloatingAction, setShowFloatingAction] = useState(false);
107
110
  const [floatingActionActive, setFloatingActionActive] = useState<false | number>(false);
@@ -312,14 +315,14 @@ export function TableComponent({
312
315
  <div className="w-max min-w-full">
313
316
  <div className="table-loading-container">
314
317
  <h1 className="table-loading-text">
315
- Memuat data...
318
+ {l.base.tableLoading ? l.base.tableLoading() : ""}
316
319
  </h1>
317
320
  </div>
318
321
  </div>
319
322
  ) : !data || !data.length ? (
320
323
  <div className="table-empty-container">
321
324
  <h1 className="table-empty-text">
322
- Belum Ada Data
325
+ {l.base.tableEmpty ? l.base.tableEmpty() : "Data empty"}
323
326
  </h1>
324
327
  </div>
325
328
  ) : (
@@ -413,7 +416,7 @@ export function TableComponent({
413
416
 
414
417
  {!!actionBulking && !!checks?.length && (
415
418
  <div className="table-bulk-actions-bar">
416
- <div className="table-bulk-actions-title">{checks?.length} Data Terpilih</div>
419
+ <div className="table-bulk-actions-title">{checks?.length} {l.base.tableSelected ? l.base.tableSelected() : ""}</div>
417
420
  <div className="table-bulk-actions-buttons">
418
421
  {actionBulking?.(checks)}
419
422
  </div>
@@ -4,8 +4,10 @@ import { useEffect, Fragment } from "react";
4
4
  import { shortcut } from "@utils"
5
5
  import { useToggleContext } from "@contexts"
6
6
  import { ModalComponent } from "../modal/Modal.component";
7
+ import { useLang } from "@skalfa/skalfa-lang";
7
8
 
8
9
  export function ShortcutProvider() {
10
+ const l = useLang();
9
11
  const { setToggle, toggle } = useToggleContext();
10
12
  const shortcuts = shortcut.list()
11
13
 
@@ -16,7 +18,7 @@ export function ShortcutProvider() {
16
18
  useEffect(() => {
17
19
  shortcut.register("ctrl+/", () => {
18
20
  setToggle("MODAL_SHORTCUT_HELP")
19
- }, "List Shortcut")
21
+ }, l.base.shortcutList ? l.base.shortcutList() : "")
20
22
  }, [])
21
23
 
22
24
  function formatShortcutKey(key: string) {
@@ -39,7 +41,7 @@ export function ShortcutProvider() {
39
41
  <ModalComponent
40
42
  show={!!toggle["MODAL_SHORTCUT_HELP"]}
41
43
  onClose={() => setToggle("MODAL_SHORTCUT_HELP")}
42
- title="Shortcut"
44
+ title={l.base.shortcut ? l.base.shortcut() : ""}
43
45
  >
44
46
  <div className="shortcut-help-grid">
45
47
  {shortcuts.map(({ key, description }) => (