@algorithm-shift/design-system 1.2.964 → 1.2.966

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.mts CHANGED
@@ -77,8 +77,15 @@ interface RadioInputProps extends ElementProps, InputSourceProperties, InputProp
77
77
  onChange?: (value: string, name: string) => void;
78
78
  }
79
79
  interface MultiCheckboxInputProps extends ElementProps, InputSourceProperties, InputProperties {
80
- value?: Record<string, boolean> | any;
81
- onChange?: (value: Record<string, boolean>, name: string) => void;
80
+ apiUrl?: string;
81
+ axiosInstance?: typeof axios;
82
+ pageSize?: number;
83
+ outputFormat?: 'array' | 'comma' | 'semicolon';
84
+ source?: 'api' | 'options' | 'json' | 'state';
85
+ loading?: boolean;
86
+ value?: string[] | string;
87
+ onUncheckItems?: (value: string[] | string, name: string) => void;
88
+ onChange?: (value: string[] | string, name: string) => void;
82
89
  }
83
90
  interface RichTextInputProps extends ElementProps, InputProperties {
84
91
  value?: string | any;
@@ -150,6 +157,8 @@ interface StagesProps extends ElementProps {
150
157
  dataKey?: string;
151
158
  dataLabel?: string;
152
159
  loading?: boolean;
160
+ triggerOnClick?: boolean;
161
+ saving?: boolean;
153
162
  }
154
163
 
155
164
  type ButtonProps = ElementProps & React.ComponentProps<"button"> & {
@@ -302,7 +311,7 @@ declare const CheckboxInput: ({ className, style, ...props }: CheckboxInputProps
302
311
 
303
312
  declare const RadioInput: ({ className, style, defaultValue, onChange, data, dataKey, dataLabel, ...props }: RadioInputProps) => react_jsx_runtime.JSX.Element;
304
313
 
305
- declare const MultiCheckbox: ({ className, style, data, dataKey, dataLabel, value: propValue, onChange, isEditable, isDisabled, ...props }: MultiCheckboxInputProps) => react_jsx_runtime.JSX.Element;
314
+ declare function MultiCheckbox({ apiUrl, axiosInstance, data, dataKey, dataLabel, pageSize, value, onChange, outputFormat, className, style, source, loading, onUncheckItems, ...props }: MultiCheckboxInputProps): react_jsx_runtime.JSX.Element;
306
315
 
307
316
  declare function RichText({ className, style, ...props }: RichTextInputProps): react_jsx_runtime.JSX.Element;
308
317
 
@@ -386,7 +395,7 @@ declare const CustomPagination: ({ totalPages, currentPage, onPageChange, maxVis
386
395
 
387
396
  declare const Tabs: ({ className, style, tabs, verticalMenu, pathname, canvasMode, isBuilder, source, parentKey, menuNameKey, menuUrlKey, loading, bgActiveColor, textActiveColor }: TabsProps) => react_jsx_runtime.JSX.Element;
388
397
 
389
- declare const StagesComponent: ({ stages, isShowBtn, buttonText, className, style, onStageChange, currentStage, dataKey, dataLabel, loading }: StagesProps) => react_jsx_runtime.JSX.Element;
398
+ declare const StagesComponent: ({ stages, isShowBtn, buttonText, className, style, onStageChange, currentStage, dataKey, dataLabel, loading, saving, triggerOnClick }: StagesProps) => react_jsx_runtime.JSX.Element;
390
399
 
391
400
  declare const Spacer: ({ className, style }: ElementProps) => react_jsx_runtime.JSX.Element;
392
401
 
package/dist/index.d.ts CHANGED
@@ -77,8 +77,15 @@ interface RadioInputProps extends ElementProps, InputSourceProperties, InputProp
77
77
  onChange?: (value: string, name: string) => void;
78
78
  }
79
79
  interface MultiCheckboxInputProps extends ElementProps, InputSourceProperties, InputProperties {
80
- value?: Record<string, boolean> | any;
81
- onChange?: (value: Record<string, boolean>, name: string) => void;
80
+ apiUrl?: string;
81
+ axiosInstance?: typeof axios;
82
+ pageSize?: number;
83
+ outputFormat?: 'array' | 'comma' | 'semicolon';
84
+ source?: 'api' | 'options' | 'json' | 'state';
85
+ loading?: boolean;
86
+ value?: string[] | string;
87
+ onUncheckItems?: (value: string[] | string, name: string) => void;
88
+ onChange?: (value: string[] | string, name: string) => void;
82
89
  }
83
90
  interface RichTextInputProps extends ElementProps, InputProperties {
84
91
  value?: string | any;
@@ -150,6 +157,8 @@ interface StagesProps extends ElementProps {
150
157
  dataKey?: string;
151
158
  dataLabel?: string;
152
159
  loading?: boolean;
160
+ triggerOnClick?: boolean;
161
+ saving?: boolean;
153
162
  }
154
163
 
155
164
  type ButtonProps = ElementProps & React.ComponentProps<"button"> & {
@@ -302,7 +311,7 @@ declare const CheckboxInput: ({ className, style, ...props }: CheckboxInputProps
302
311
 
303
312
  declare const RadioInput: ({ className, style, defaultValue, onChange, data, dataKey, dataLabel, ...props }: RadioInputProps) => react_jsx_runtime.JSX.Element;
304
313
 
305
- declare const MultiCheckbox: ({ className, style, data, dataKey, dataLabel, value: propValue, onChange, isEditable, isDisabled, ...props }: MultiCheckboxInputProps) => react_jsx_runtime.JSX.Element;
314
+ declare function MultiCheckbox({ apiUrl, axiosInstance, data, dataKey, dataLabel, pageSize, value, onChange, outputFormat, className, style, source, loading, onUncheckItems, ...props }: MultiCheckboxInputProps): react_jsx_runtime.JSX.Element;
306
315
 
307
316
  declare function RichText({ className, style, ...props }: RichTextInputProps): react_jsx_runtime.JSX.Element;
308
317
 
@@ -386,7 +395,7 @@ declare const CustomPagination: ({ totalPages, currentPage, onPageChange, maxVis
386
395
 
387
396
  declare const Tabs: ({ className, style, tabs, verticalMenu, pathname, canvasMode, isBuilder, source, parentKey, menuNameKey, menuUrlKey, loading, bgActiveColor, textActiveColor }: TabsProps) => react_jsx_runtime.JSX.Element;
388
397
 
389
- declare const StagesComponent: ({ stages, isShowBtn, buttonText, className, style, onStageChange, currentStage, dataKey, dataLabel, loading }: StagesProps) => react_jsx_runtime.JSX.Element;
398
+ declare const StagesComponent: ({ stages, isShowBtn, buttonText, className, style, onStageChange, currentStage, dataKey, dataLabel, loading, saving, triggerOnClick }: StagesProps) => react_jsx_runtime.JSX.Element;
390
399
 
391
400
  declare const Spacer: ({ className, style }: ElementProps) => react_jsx_runtime.JSX.Element;
392
401
 
package/dist/index.js CHANGED
@@ -50,7 +50,7 @@ __export(src_exports, {
50
50
  Icon: () => Icon_default,
51
51
  Image: () => Image_default,
52
52
  Modal: () => Modal,
53
- MultiCheckbox: () => MultiCheckbox_default,
53
+ MultiCheckbox: () => MultiCheckbox,
54
54
  MultiSelect: () => LazyMultiSelectDropdown,
55
55
  Navbar: () => Navbar,
56
56
  NumberInput: () => NumberInput_default,
@@ -27455,63 +27455,160 @@ var RadioInput_default = RadioInput;
27455
27455
  // src/components/Inputs/MultiCheckbox/MultiCheckbox.tsx
27456
27456
  var import_react16 = require("react");
27457
27457
  var import_jsx_runtime32 = require("react/jsx-runtime");
27458
- var MultiCheckbox = ({
27459
- className,
27460
- style,
27458
+ function MultiCheckbox({
27459
+ apiUrl,
27460
+ axiosInstance,
27461
27461
  data = [],
27462
- dataKey = "value",
27463
- dataLabel = "label",
27464
- value: propValue = {},
27462
+ dataKey = "id",
27463
+ dataLabel = "name",
27464
+ pageSize = 20,
27465
+ value,
27465
27466
  onChange,
27466
- isEditable = true,
27467
- isDisabled = false,
27467
+ outputFormat = "array",
27468
+ className,
27469
+ style,
27470
+ source,
27471
+ loading,
27472
+ onUncheckItems,
27468
27473
  ...props
27469
- }) => {
27470
- const list = Array.isArray(data) ? data : [];
27471
- const [value, setValue] = (0, import_react16.useState)(propValue);
27472
- const options = (list || []).map((item) => ({
27473
- value: item[dataKey || "value"],
27474
- label: item[dataLabel || "label"]
27475
- }));
27476
- (0, import_react16.useEffect)(() => {
27477
- if (propValue !== void 0) {
27478
- onChange?.(propValue, props?.name || "");
27474
+ }) {
27475
+ const [options, setOptions] = (0, import_react16.useState)([]);
27476
+ const [page, setPage] = (0, import_react16.useState)(1);
27477
+ const [hasMore, setHasMore] = (0, import_react16.useState)(true);
27478
+ const [pageLoading, setPageLoading] = (0, import_react16.useState)(false);
27479
+ const loadMoreRef = (0, import_react16.useRef)(null);
27480
+ const normalizeInput = (val) => {
27481
+ if (!val) return [];
27482
+ if (Array.isArray(val)) return val;
27483
+ if (typeof val === "string") {
27484
+ if (val.includes(";")) return val.split(";").map((s) => s.trim());
27485
+ if (val.includes(",")) return val.split(",").map((s) => s.trim());
27486
+ return [val.trim()];
27479
27487
  }
27480
- }, []);
27481
- const handleChange = (0, import_react16.useCallback)(
27482
- (key, checked) => {
27483
- setValue((prev) => {
27484
- const newValue = { ...prev, [key]: checked };
27485
- onChange?.(newValue, props?.name || "");
27486
- return newValue;
27487
- });
27488
+ return [];
27489
+ };
27490
+ const selected = normalizeInput(value);
27491
+ const convertOutput = (arr) => {
27492
+ switch (outputFormat) {
27493
+ case "comma":
27494
+ return arr.join(",");
27495
+ case "semicolon":
27496
+ return arr.join(";");
27497
+ default:
27498
+ return arr;
27499
+ }
27500
+ };
27501
+ const fetchApiPage = (0, import_react16.useCallback)(async () => {
27502
+ if (!apiUrl) return [];
27503
+ const client = axiosInstance || (await import("axios")).default;
27504
+ const res = await client.get(apiUrl, {
27505
+ params: { page, limit: pageSize },
27506
+ withCredentials: true
27507
+ });
27508
+ if (res.data?.success && Array.isArray(res.data.data)) {
27509
+ return res.data.data;
27510
+ }
27511
+ return Array.isArray(res.data) ? res.data : [];
27512
+ }, [apiUrl, axiosInstance, page, pageSize]);
27513
+ const mapData = (0, import_react16.useCallback)(
27514
+ (items) => {
27515
+ if (Array.isArray(items) === false) return [];
27516
+ return (items || []).map((item) => ({
27517
+ value: item[dataKey],
27518
+ label: item[dataLabel]
27519
+ }));
27488
27520
  },
27489
- [onChange]
27521
+ [dataKey, dataLabel]
27490
27522
  );
27491
- return /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)(
27492
- "div",
27493
- {
27494
- className: cn("flex flex-col gap-3", className),
27495
- style,
27496
- children: [
27497
- options.length === 0 && /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("p", { className: "text-sm text-gray-500", children: "No options available." }),
27498
- options.map((opt) => /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)("div", { className: "flex items-center space-x-2", children: [
27499
- /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
27500
- Checkbox,
27501
- {
27502
- id: opt.value,
27503
- checked: !!value[opt.value],
27504
- onCheckedChange: (checked) => handleChange(opt.value, checked === true),
27505
- disabled: !isEditable || isDisabled
27506
- }
27507
- ),
27508
- /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(Label2, { htmlFor: opt.value, children: opt.label })
27509
- ] }, opt.value))
27510
- ]
27523
+ const loadPage = (0, import_react16.useCallback)(async () => {
27524
+ if (source !== "api") return;
27525
+ if (pageLoading) return;
27526
+ setPageLoading(true);
27527
+ try {
27528
+ const pageData = await fetchApiPage();
27529
+ const mapped = mapData(pageData);
27530
+ setOptions((prev) => [...prev, ...mapped]);
27531
+ if (pageData.length < pageSize) {
27532
+ setHasMore(false);
27533
+ }
27534
+ } finally {
27535
+ setPageLoading(false);
27511
27536
  }
27512
- );
27513
- };
27514
- var MultiCheckbox_default = MultiCheckbox;
27537
+ }, [source, pageLoading, fetchApiPage, mapData, pageSize]);
27538
+ (0, import_react16.useEffect)(() => {
27539
+ if (source === "api") {
27540
+ setOptions([]);
27541
+ setPage(1);
27542
+ setHasMore(true);
27543
+ } else {
27544
+ setOptions(mapData(data));
27545
+ setHasMore(false);
27546
+ }
27547
+ }, [source, JSON.stringify(data)]);
27548
+ (0, import_react16.useEffect)(() => {
27549
+ if (source === "api") loadPage();
27550
+ }, [page, source]);
27551
+ (0, import_react16.useEffect)(() => {
27552
+ if (source !== "api") return;
27553
+ if (!hasMore || pageLoading) return;
27554
+ const observer = new IntersectionObserver((entries) => {
27555
+ if (entries[0].isIntersecting) {
27556
+ setPage((prev) => prev + 1);
27557
+ }
27558
+ });
27559
+ if (loadMoreRef.current) observer.observe(loadMoreRef.current);
27560
+ return () => observer.disconnect();
27561
+ }, [source, hasMore, pageLoading]);
27562
+ const toggle = (val) => {
27563
+ if (props.isDisabled || props.isReadonly) return;
27564
+ const updated = selected.includes(val) ? selected.filter((v) => v !== val) : [...selected, val];
27565
+ onChange?.(convertOutput(updated), props.name || "");
27566
+ onUncheckItems?.(convertOutput(
27567
+ options.filter((opt) => !updated.includes(opt.value)).map((opt) => opt.value)
27568
+ ), props.name || "");
27569
+ };
27570
+ return /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)("div", { className: cn("flex flex-col gap-2 max-h-64 overflow-auto", className), style, children: [
27571
+ options.length === 0 && !pageLoading && !loading && /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("div", { className: "text-center py-2 text-gray-500 text-sm", children: "No options available." }),
27572
+ options.map((opt, index) => {
27573
+ const hasError = !!props.errorMessage;
27574
+ return /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)(
27575
+ "div",
27576
+ {
27577
+ className: cn(
27578
+ "flex items-center space-x-2 p-1 rounded",
27579
+ hasError && "bg-red-50"
27580
+ ),
27581
+ children: [
27582
+ /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
27583
+ Checkbox,
27584
+ {
27585
+ id: props.name ? `${props.name}-${opt.value}` : opt.value,
27586
+ checked: selected.includes(opt.value),
27587
+ onCheckedChange: () => toggle(opt.value),
27588
+ disabled: props.isDisabled || props.isReadonly,
27589
+ className: cn(
27590
+ hasError && "border-red-500 data-[state=checked]:bg-red-500"
27591
+ )
27592
+ }
27593
+ ),
27594
+ /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
27595
+ Label2,
27596
+ {
27597
+ id: props.name ? `${props.name}-${opt.value}` : opt.value,
27598
+ className: cn(hasError && "text-red-600"),
27599
+ children: opt.label
27600
+ }
27601
+ )
27602
+ ]
27603
+ },
27604
+ `${index}-${opt.value}`
27605
+ );
27606
+ }),
27607
+ source === "api" && hasMore && /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("div", { ref: loadMoreRef, className: "h-4" }),
27608
+ (pageLoading || loading) && /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("div", { className: "text-center py-2 text-gray-500 text-sm", children: "Loading\u2026" }),
27609
+ props.errorMessage && /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("p", { className: "mt-1 text-xs text-red-500", children: props.errorMessage })
27610
+ ] });
27611
+ }
27515
27612
 
27516
27613
  // src/components/Inputs/RichText/RichText.tsx
27517
27614
  var import_react18 = require("react");
@@ -30374,24 +30471,38 @@ var Tabs_default = Tabs;
30374
30471
  // src/components/Navigation/Stages/Stages.tsx
30375
30472
  var import_react32 = __toESM(require("react"));
30376
30473
  var import_jsx_runtime57 = require("react/jsx-runtime");
30377
- var StagesComponent = ({ stages, isShowBtn, buttonText, className, style, onStageChange, currentStage, dataKey = "key", dataLabel = "header", loading }) => {
30474
+ var StagesComponent = ({ stages, isShowBtn, buttonText, className, style, onStageChange, currentStage, dataKey = "key", dataLabel = "header", loading, saving, triggerOnClick = false }) => {
30378
30475
  const [activeStage, setActiveStage] = (0, import_react32.useState)(currentStage || (stages && stages.length > 0 ? stages[0].key : null));
30476
+ const [isCompleted, setIsCompleted] = (0, import_react32.useState)(false);
30477
+ const updateStage = (stageKey) => {
30478
+ setActiveStage(stageKey);
30479
+ onStageChange?.(stageKey);
30480
+ };
30379
30481
  const nextStage = () => {
30380
30482
  if (!stages || stages.length === 0) return;
30381
30483
  const currentIndex = stages.findIndex((stage) => stage[dataKey] === activeStage);
30382
- if (currentIndex < stages.length - 1) {
30383
- const newStage = stages[currentIndex + 1];
30384
- setActiveStage(newStage[dataKey]);
30385
- onStageChange?.(newStage[dataKey]);
30484
+ if (currentIndex + 1 === stages.length) {
30485
+ const currentStage2 = stages[currentIndex];
30486
+ updateStage(currentStage2[dataKey]);
30487
+ setIsCompleted(true);
30488
+ return;
30489
+ }
30490
+ if (currentIndex < stages.length) {
30491
+ const currentStage2 = stages[currentIndex];
30492
+ updateStage(currentStage2[dataKey]);
30493
+ return;
30386
30494
  }
30387
30495
  };
30388
30496
  const lastStage = stages && stages.length > 0 ? stages[stages.length - 1][dataKey] : null;
30389
30497
  const onStageClick = (stageKey) => {
30390
30498
  if (!stageKey || stageKey === activeStage || activeStage === lastStage) return;
30391
30499
  setActiveStage(stageKey);
30392
- onStageChange?.(stageKey);
30500
+ if (triggerOnClick) {
30501
+ onStageChange?.(stageKey);
30502
+ }
30393
30503
  };
30394
- const isAllStagesCompleted = activeStage === lastStage;
30504
+ const isAllStagesCompleted = isCompleted || currentStage === lastStage;
30505
+ const disabled = isAllStagesCompleted || loading || saving;
30395
30506
  return /* @__PURE__ */ (0, import_jsx_runtime57.jsx)("div", { className, style, children: /* @__PURE__ */ (0, import_jsx_runtime57.jsxs)("div", { className: "flex items-center justify-between bg-red p-2 rounded-lg border border-gray-200 w-full", children: [
30396
30507
  /* @__PURE__ */ (0, import_jsx_runtime57.jsx)("div", { className: "flex items-center", children: /* @__PURE__ */ (0, import_jsx_runtime57.jsx)("button", { className: "p-2 hover:bg-gray-100 rounded", children: /* @__PURE__ */ (0, import_jsx_runtime57.jsx)("svg", { className: "w-4 h-4 text-gray-600", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ (0, import_jsx_runtime57.jsx)("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M19 9l-7 7-7-7" }) }) }) }),
30397
30508
  /* @__PURE__ */ (0, import_jsx_runtime57.jsx)("div", { className: "flex items-center flex-1 px-2 flex-wrap gap-2", children: loading ? Array(6).fill(null).map((_, index) => /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(
@@ -30405,7 +30516,7 @@ var StagesComponent = ({ stages, isShowBtn, buttonText, className, style, onStag
30405
30516
  index
30406
30517
  )) : stages?.length > 0 && stages?.map((stage, index) => {
30407
30518
  const currentIndex = stages.findIndex((s) => s[dataKey] === activeStage);
30408
- const isCompleted = isAllStagesCompleted || index < currentIndex;
30519
+ const isCompleted2 = isAllStagesCompleted || index < currentIndex;
30409
30520
  const isActive = !isAllStagesCompleted && index === currentIndex;
30410
30521
  return /* @__PURE__ */ (0, import_jsx_runtime57.jsxs)(import_react32.default.Fragment, { children: [
30411
30522
  /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(
@@ -30413,7 +30524,7 @@ var StagesComponent = ({ stages, isShowBtn, buttonText, className, style, onStag
30413
30524
  {
30414
30525
  className: `
30415
30526
  min-w-[80px] px-4 py-2 rounded-full text-sm font-medium transition-colors duration-200 whitespace-nowrap
30416
- ${isActive ? "bg-green-700 text-white shadow-md" : isCompleted ? "bg-green-50 text-green-700 border border-green-700" : "bg-white text-gray-700 hover:bg-gray-100 border border-gray-200"}`,
30527
+ ${isActive ? "bg-green-700 text-white shadow-md" : isCompleted2 ? "bg-green-50 text-green-700 border border-green-700" : "bg-white text-gray-700 hover:bg-gray-100 border border-gray-200"}`,
30417
30528
  onClick: () => {
30418
30529
  if (isAllStagesCompleted) return;
30419
30530
  onStageClick(stage[dataKey]);
@@ -30427,11 +30538,12 @@ var StagesComponent = ({ stages, isShowBtn, buttonText, className, style, onStag
30427
30538
  isShowBtn && /* @__PURE__ */ (0, import_jsx_runtime57.jsx)("div", { className: "flex items-center", children: /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(
30428
30539
  "button",
30429
30540
  {
30430
- className: "bg-green-700 text-white px-6 py-2 rounded-lg text-sm font-medium transition-colors duration-200 shadow-sm",
30541
+ className: `bg-green-700 text-white px-6 py-2 rounded-lg text-sm font-medium transition-colors duration-200 shadow-sm ${disabled ? "opacity-50 cursor-not-allowed" : ""}`,
30431
30542
  onClick: () => {
30432
30543
  nextStage();
30433
30544
  },
30434
- children: buttonText
30545
+ disabled,
30546
+ children: saving ? "Updating..." : buttonText
30435
30547
  }
30436
30548
  ) })
30437
30549
  ] }) });