@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.mjs CHANGED
@@ -27358,71 +27358,168 @@ var RadioInput = ({
27358
27358
  var RadioInput_default = RadioInput;
27359
27359
 
27360
27360
  // src/components/Inputs/MultiCheckbox/MultiCheckbox.tsx
27361
- import { useCallback, useEffect as useEffect11, useState as useState3 } from "react";
27361
+ import { useEffect as useEffect11, useState as useState3, useRef, useCallback } from "react";
27362
27362
  import { jsx as jsx32, jsxs as jsxs15 } from "react/jsx-runtime";
27363
- var MultiCheckbox = ({
27364
- className,
27365
- style,
27363
+ function MultiCheckbox({
27364
+ apiUrl,
27365
+ axiosInstance,
27366
27366
  data = [],
27367
- dataKey = "value",
27368
- dataLabel = "label",
27369
- value: propValue = {},
27367
+ dataKey = "id",
27368
+ dataLabel = "name",
27369
+ pageSize = 20,
27370
+ value,
27370
27371
  onChange,
27371
- isEditable = true,
27372
- isDisabled = false,
27372
+ outputFormat = "array",
27373
+ className,
27374
+ style,
27375
+ source,
27376
+ loading,
27377
+ onUncheckItems,
27373
27378
  ...props
27374
- }) => {
27375
- const list = Array.isArray(data) ? data : [];
27376
- const [value, setValue] = useState3(propValue);
27377
- const options = (list || []).map((item) => ({
27378
- value: item[dataKey || "value"],
27379
- label: item[dataLabel || "label"]
27380
- }));
27381
- useEffect11(() => {
27382
- if (propValue !== void 0) {
27383
- onChange?.(propValue, props?.name || "");
27379
+ }) {
27380
+ const [options, setOptions] = useState3([]);
27381
+ const [page, setPage] = useState3(1);
27382
+ const [hasMore, setHasMore] = useState3(true);
27383
+ const [pageLoading, setPageLoading] = useState3(false);
27384
+ const loadMoreRef = useRef(null);
27385
+ const normalizeInput = (val) => {
27386
+ if (!val) return [];
27387
+ if (Array.isArray(val)) return val;
27388
+ if (typeof val === "string") {
27389
+ if (val.includes(";")) return val.split(";").map((s) => s.trim());
27390
+ if (val.includes(",")) return val.split(",").map((s) => s.trim());
27391
+ return [val.trim()];
27384
27392
  }
27385
- }, []);
27386
- const handleChange = useCallback(
27387
- (key, checked) => {
27388
- setValue((prev) => {
27389
- const newValue = { ...prev, [key]: checked };
27390
- onChange?.(newValue, props?.name || "");
27391
- return newValue;
27392
- });
27393
+ return [];
27394
+ };
27395
+ const selected = normalizeInput(value);
27396
+ const convertOutput = (arr) => {
27397
+ switch (outputFormat) {
27398
+ case "comma":
27399
+ return arr.join(",");
27400
+ case "semicolon":
27401
+ return arr.join(";");
27402
+ default:
27403
+ return arr;
27404
+ }
27405
+ };
27406
+ const fetchApiPage = useCallback(async () => {
27407
+ if (!apiUrl) return [];
27408
+ const client = axiosInstance || (await import("axios")).default;
27409
+ const res = await client.get(apiUrl, {
27410
+ params: { page, limit: pageSize },
27411
+ withCredentials: true
27412
+ });
27413
+ if (res.data?.success && Array.isArray(res.data.data)) {
27414
+ return res.data.data;
27415
+ }
27416
+ return Array.isArray(res.data) ? res.data : [];
27417
+ }, [apiUrl, axiosInstance, page, pageSize]);
27418
+ const mapData = useCallback(
27419
+ (items) => {
27420
+ if (Array.isArray(items) === false) return [];
27421
+ return (items || []).map((item) => ({
27422
+ value: item[dataKey],
27423
+ label: item[dataLabel]
27424
+ }));
27393
27425
  },
27394
- [onChange]
27426
+ [dataKey, dataLabel]
27395
27427
  );
27396
- return /* @__PURE__ */ jsxs15(
27397
- "div",
27398
- {
27399
- className: cn("flex flex-col gap-3", className),
27400
- style,
27401
- children: [
27402
- options.length === 0 && /* @__PURE__ */ jsx32("p", { className: "text-sm text-gray-500", children: "No options available." }),
27403
- options.map((opt) => /* @__PURE__ */ jsxs15("div", { className: "flex items-center space-x-2", children: [
27404
- /* @__PURE__ */ jsx32(
27405
- Checkbox,
27406
- {
27407
- id: opt.value,
27408
- checked: !!value[opt.value],
27409
- onCheckedChange: (checked) => handleChange(opt.value, checked === true),
27410
- disabled: !isEditable || isDisabled
27411
- }
27412
- ),
27413
- /* @__PURE__ */ jsx32(Label2, { htmlFor: opt.value, children: opt.label })
27414
- ] }, opt.value))
27415
- ]
27428
+ const loadPage = useCallback(async () => {
27429
+ if (source !== "api") return;
27430
+ if (pageLoading) return;
27431
+ setPageLoading(true);
27432
+ try {
27433
+ const pageData = await fetchApiPage();
27434
+ const mapped = mapData(pageData);
27435
+ setOptions((prev) => [...prev, ...mapped]);
27436
+ if (pageData.length < pageSize) {
27437
+ setHasMore(false);
27438
+ }
27439
+ } finally {
27440
+ setPageLoading(false);
27416
27441
  }
27417
- );
27418
- };
27419
- var MultiCheckbox_default = MultiCheckbox;
27442
+ }, [source, pageLoading, fetchApiPage, mapData, pageSize]);
27443
+ useEffect11(() => {
27444
+ if (source === "api") {
27445
+ setOptions([]);
27446
+ setPage(1);
27447
+ setHasMore(true);
27448
+ } else {
27449
+ setOptions(mapData(data));
27450
+ setHasMore(false);
27451
+ }
27452
+ }, [source, JSON.stringify(data)]);
27453
+ useEffect11(() => {
27454
+ if (source === "api") loadPage();
27455
+ }, [page, source]);
27456
+ useEffect11(() => {
27457
+ if (source !== "api") return;
27458
+ if (!hasMore || pageLoading) return;
27459
+ const observer = new IntersectionObserver((entries) => {
27460
+ if (entries[0].isIntersecting) {
27461
+ setPage((prev) => prev + 1);
27462
+ }
27463
+ });
27464
+ if (loadMoreRef.current) observer.observe(loadMoreRef.current);
27465
+ return () => observer.disconnect();
27466
+ }, [source, hasMore, pageLoading]);
27467
+ const toggle = (val) => {
27468
+ if (props.isDisabled || props.isReadonly) return;
27469
+ const updated = selected.includes(val) ? selected.filter((v) => v !== val) : [...selected, val];
27470
+ onChange?.(convertOutput(updated), props.name || "");
27471
+ onUncheckItems?.(convertOutput(
27472
+ options.filter((opt) => !updated.includes(opt.value)).map((opt) => opt.value)
27473
+ ), props.name || "");
27474
+ };
27475
+ return /* @__PURE__ */ jsxs15("div", { className: cn("flex flex-col gap-2 max-h-64 overflow-auto", className), style, children: [
27476
+ options.length === 0 && !pageLoading && !loading && /* @__PURE__ */ jsx32("div", { className: "text-center py-2 text-gray-500 text-sm", children: "No options available." }),
27477
+ options.map((opt, index) => {
27478
+ const hasError = !!props.errorMessage;
27479
+ return /* @__PURE__ */ jsxs15(
27480
+ "div",
27481
+ {
27482
+ className: cn(
27483
+ "flex items-center space-x-2 p-1 rounded",
27484
+ hasError && "bg-red-50"
27485
+ ),
27486
+ children: [
27487
+ /* @__PURE__ */ jsx32(
27488
+ Checkbox,
27489
+ {
27490
+ id: props.name ? `${props.name}-${opt.value}` : opt.value,
27491
+ checked: selected.includes(opt.value),
27492
+ onCheckedChange: () => toggle(opt.value),
27493
+ disabled: props.isDisabled || props.isReadonly,
27494
+ className: cn(
27495
+ hasError && "border-red-500 data-[state=checked]:bg-red-500"
27496
+ )
27497
+ }
27498
+ ),
27499
+ /* @__PURE__ */ jsx32(
27500
+ Label2,
27501
+ {
27502
+ id: props.name ? `${props.name}-${opt.value}` : opt.value,
27503
+ className: cn(hasError && "text-red-600"),
27504
+ children: opt.label
27505
+ }
27506
+ )
27507
+ ]
27508
+ },
27509
+ `${index}-${opt.value}`
27510
+ );
27511
+ }),
27512
+ source === "api" && hasMore && /* @__PURE__ */ jsx32("div", { ref: loadMoreRef, className: "h-4" }),
27513
+ (pageLoading || loading) && /* @__PURE__ */ jsx32("div", { className: "text-center py-2 text-gray-500 text-sm", children: "Loading\u2026" }),
27514
+ props.errorMessage && /* @__PURE__ */ jsx32("p", { className: "mt-1 text-xs text-red-500", children: props.errorMessage })
27515
+ ] });
27516
+ }
27420
27517
 
27421
27518
  // src/components/Inputs/RichText/RichText.tsx
27422
27519
  import { useEffect as useEffect12 } from "react";
27423
27520
 
27424
27521
  // src/components/Global/TinyMceEditor.tsx
27425
- import { useMemo as useMemo2, useRef } from "react";
27522
+ import { useMemo as useMemo2, useRef as useRef2 } from "react";
27426
27523
  import { Editor } from "@tinymce/tinymce-react";
27427
27524
  import { jsx as jsx33 } from "react/jsx-runtime";
27428
27525
  function MyEditor({
@@ -27430,7 +27527,7 @@ function MyEditor({
27430
27527
  onChange,
27431
27528
  isDefault
27432
27529
  }) {
27433
- const editorRef = useRef(null);
27530
+ const editorRef = useRef2(null);
27434
27531
  function stripOuterP(html) {
27435
27532
  const trimmedHtml = html.trim();
27436
27533
  if (!trimmedHtml) return "";
@@ -27649,10 +27746,10 @@ function SelectScrollDownButton({
27649
27746
  }
27650
27747
 
27651
27748
  // src/components/Inputs/Dropdown/LazyDropdown.tsx
27652
- import { useState as useState5, useRef as useRef3, useEffect as useEffect14, useMemo as useMemo3 } from "react";
27749
+ import { useState as useState5, useRef as useRef4, useEffect as useEffect14, useMemo as useMemo3 } from "react";
27653
27750
 
27654
27751
  // src/hooks/useLazyDropdown.ts
27655
- import { useState as useState4, useEffect as useEffect13, useRef as useRef2, useCallback as useCallback2 } from "react";
27752
+ import { useState as useState4, useEffect as useEffect13, useRef as useRef3, useCallback as useCallback2 } from "react";
27656
27753
  import axios from "axios";
27657
27754
  function useLazyDropdown(config) {
27658
27755
  const [options, setOptions] = useState4([]);
@@ -27660,9 +27757,9 @@ function useLazyDropdown(config) {
27660
27757
  const [hasMore, setHasMore] = useState4(true);
27661
27758
  const [loading, setLoading] = useState4(false);
27662
27759
  const [searchTerm, setSearchTerm] = useState4("");
27663
- const debounceTimer = useRef2(null);
27664
- const allDataRef = useRef2([]);
27665
- const configRef = useRef2(config);
27760
+ const debounceTimer = useRef3(null);
27761
+ const allDataRef = useRef3([]);
27762
+ const configRef = useRef3(config);
27666
27763
  const PAGE_SIZE = config.pageSize || 10;
27667
27764
  const uniqueOptions = (items) => {
27668
27765
  const seen = /* @__PURE__ */ new Set();
@@ -27839,8 +27936,8 @@ function LazySelectDropdown({
27839
27936
  }) {
27840
27937
  const [isOpen, setIsOpen] = useState5(false);
27841
27938
  const [searchTerm, setSearchTerm] = useState5("");
27842
- const dropdownRef = useRef3(null);
27843
- const observerTarget = useRef3(null);
27939
+ const dropdownRef = useRef4(null);
27940
+ const observerTarget = useRef4(null);
27844
27941
  const {
27845
27942
  options: lazyOptions,
27846
27943
  loading,
@@ -28659,7 +28756,7 @@ var TextInputGroup = ({ className, style, prepend, append, ...props }) => {
28659
28756
  var TextInputGroup_default = TextInputGroup;
28660
28757
 
28661
28758
  // src/components/Inputs/Multiselect/MultiSelect.tsx
28662
- import { useState as useState6, useRef as useRef5, useEffect as useEffect24, useMemo as useMemo4 } from "react";
28759
+ import { useState as useState6, useRef as useRef6, useEffect as useEffect24, useMemo as useMemo4 } from "react";
28663
28760
  import { Fragment as Fragment19, jsx as jsx48, jsxs as jsxs27 } from "react/jsx-runtime";
28664
28761
  function LazyMultiSelectDropdown({
28665
28762
  options = [],
@@ -28681,8 +28778,8 @@ function LazyMultiSelectDropdown({
28681
28778
  }) {
28682
28779
  const [isOpen, setIsOpen] = useState6(false);
28683
28780
  const [searchTerm, setSearchTerm] = useState6("");
28684
- const dropdownRef = useRef5(null);
28685
- const observerTarget = useRef5(null);
28781
+ const dropdownRef = useRef6(null);
28782
+ const observerTarget = useRef6(null);
28686
28783
  const {
28687
28784
  options: lazyOptions,
28688
28785
  loading,
@@ -30285,24 +30382,38 @@ var Tabs_default = Tabs;
30285
30382
  // src/components/Navigation/Stages/Stages.tsx
30286
30383
  import React10, { useState as useState9 } from "react";
30287
30384
  import { jsx as jsx57, jsxs as jsxs34 } from "react/jsx-runtime";
30288
- var StagesComponent = ({ stages, isShowBtn, buttonText, className, style, onStageChange, currentStage, dataKey = "key", dataLabel = "header", loading }) => {
30385
+ var StagesComponent = ({ stages, isShowBtn, buttonText, className, style, onStageChange, currentStage, dataKey = "key", dataLabel = "header", loading, saving, triggerOnClick = false }) => {
30289
30386
  const [activeStage, setActiveStage] = useState9(currentStage || (stages && stages.length > 0 ? stages[0].key : null));
30387
+ const [isCompleted, setIsCompleted] = useState9(false);
30388
+ const updateStage = (stageKey) => {
30389
+ setActiveStage(stageKey);
30390
+ onStageChange?.(stageKey);
30391
+ };
30290
30392
  const nextStage = () => {
30291
30393
  if (!stages || stages.length === 0) return;
30292
30394
  const currentIndex = stages.findIndex((stage) => stage[dataKey] === activeStage);
30293
- if (currentIndex < stages.length - 1) {
30294
- const newStage = stages[currentIndex + 1];
30295
- setActiveStage(newStage[dataKey]);
30296
- onStageChange?.(newStage[dataKey]);
30395
+ if (currentIndex + 1 === stages.length) {
30396
+ const currentStage2 = stages[currentIndex];
30397
+ updateStage(currentStage2[dataKey]);
30398
+ setIsCompleted(true);
30399
+ return;
30400
+ }
30401
+ if (currentIndex < stages.length) {
30402
+ const currentStage2 = stages[currentIndex];
30403
+ updateStage(currentStage2[dataKey]);
30404
+ return;
30297
30405
  }
30298
30406
  };
30299
30407
  const lastStage = stages && stages.length > 0 ? stages[stages.length - 1][dataKey] : null;
30300
30408
  const onStageClick = (stageKey) => {
30301
30409
  if (!stageKey || stageKey === activeStage || activeStage === lastStage) return;
30302
30410
  setActiveStage(stageKey);
30303
- onStageChange?.(stageKey);
30411
+ if (triggerOnClick) {
30412
+ onStageChange?.(stageKey);
30413
+ }
30304
30414
  };
30305
- const isAllStagesCompleted = activeStage === lastStage;
30415
+ const isAllStagesCompleted = isCompleted || currentStage === lastStage;
30416
+ const disabled = isAllStagesCompleted || loading || saving;
30306
30417
  return /* @__PURE__ */ jsx57("div", { className, style, children: /* @__PURE__ */ jsxs34("div", { className: "flex items-center justify-between bg-red p-2 rounded-lg border border-gray-200 w-full", children: [
30307
30418
  /* @__PURE__ */ jsx57("div", { className: "flex items-center", children: /* @__PURE__ */ jsx57("button", { className: "p-2 hover:bg-gray-100 rounded", children: /* @__PURE__ */ jsx57("svg", { className: "w-4 h-4 text-gray-600", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx57("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M19 9l-7 7-7-7" }) }) }) }),
30308
30419
  /* @__PURE__ */ jsx57("div", { className: "flex items-center flex-1 px-2 flex-wrap gap-2", children: loading ? Array(6).fill(null).map((_, index) => /* @__PURE__ */ jsx57(
@@ -30316,7 +30427,7 @@ var StagesComponent = ({ stages, isShowBtn, buttonText, className, style, onStag
30316
30427
  index
30317
30428
  )) : stages?.length > 0 && stages?.map((stage, index) => {
30318
30429
  const currentIndex = stages.findIndex((s) => s[dataKey] === activeStage);
30319
- const isCompleted = isAllStagesCompleted || index < currentIndex;
30430
+ const isCompleted2 = isAllStagesCompleted || index < currentIndex;
30320
30431
  const isActive = !isAllStagesCompleted && index === currentIndex;
30321
30432
  return /* @__PURE__ */ jsxs34(React10.Fragment, { children: [
30322
30433
  /* @__PURE__ */ jsx57(
@@ -30324,7 +30435,7 @@ var StagesComponent = ({ stages, isShowBtn, buttonText, className, style, onStag
30324
30435
  {
30325
30436
  className: `
30326
30437
  min-w-[80px] px-4 py-2 rounded-full text-sm font-medium transition-colors duration-200 whitespace-nowrap
30327
- ${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"}`,
30438
+ ${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"}`,
30328
30439
  onClick: () => {
30329
30440
  if (isAllStagesCompleted) return;
30330
30441
  onStageClick(stage[dataKey]);
@@ -30338,11 +30449,12 @@ var StagesComponent = ({ stages, isShowBtn, buttonText, className, style, onStag
30338
30449
  isShowBtn && /* @__PURE__ */ jsx57("div", { className: "flex items-center", children: /* @__PURE__ */ jsx57(
30339
30450
  "button",
30340
30451
  {
30341
- className: "bg-green-700 text-white px-6 py-2 rounded-lg text-sm font-medium transition-colors duration-200 shadow-sm",
30452
+ 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" : ""}`,
30342
30453
  onClick: () => {
30343
30454
  nextStage();
30344
30455
  },
30345
- children: buttonText
30456
+ disabled,
30457
+ children: saving ? "Updating..." : buttonText
30346
30458
  }
30347
30459
  ) })
30348
30460
  ] }) });
@@ -30876,7 +30988,7 @@ export {
30876
30988
  Icon_default as Icon,
30877
30989
  Image_default as Image,
30878
30990
  Modal,
30879
- MultiCheckbox_default as MultiCheckbox,
30991
+ MultiCheckbox,
30880
30992
  LazyMultiSelectDropdown as MultiSelect,
30881
30993
  Navbar,
30882
30994
  NumberInput_default as NumberInput,