@janbox/storefront-ui 1.0.3 → 1.0.5

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.
Files changed (30) hide show
  1. package/dist/components/virtualized-list.d.ts +2 -2
  2. package/dist/components/virtualized-list.d.ts.map +1 -1
  3. package/dist/components/virtualized-list.js +15 -2
  4. package/dist/hooks/index.d.ts +1 -0
  5. package/dist/hooks/index.d.ts.map +1 -1
  6. package/dist/hooks/index.js +2 -0
  7. package/dist/hooks/use-controllable-state.js +1 -1
  8. package/dist/hooks/use-countdown-timer.js +1 -1
  9. package/dist/hooks/use-deep-compare-effect/index.d.ts +3 -0
  10. package/dist/hooks/use-deep-compare-effect/index.d.ts.map +1 -0
  11. package/dist/hooks/use-deep-compare-effect/index.js +15 -0
  12. package/dist/lib/cascader/cascader-floating-content.d.ts +30 -0
  13. package/dist/lib/cascader/cascader-floating-content.d.ts.map +1 -0
  14. package/dist/lib/cascader/cascader-floating-content.js +411 -0
  15. package/dist/lib/cascader/cascader.d.ts +2 -2
  16. package/dist/lib/cascader/cascader.d.ts.map +1 -1
  17. package/dist/lib/cascader/cascader.js +33 -363
  18. package/dist/lib/cascader/helpers.d.ts +10 -6
  19. package/dist/lib/cascader/helpers.d.ts.map +1 -1
  20. package/dist/lib/cascader/helpers.js +8 -2
  21. package/dist/lib/cascader/types.d.ts +17 -11
  22. package/dist/lib/cascader/types.d.ts.map +1 -1
  23. package/dist/types/index.d.ts +12 -1
  24. package/dist/types/index.d.ts.map +1 -1
  25. package/package.json +1 -2
  26. package/dist/node_modules/.pnpm/react-use@17.6.0_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/react-use/esm/misc/isDeepEqual.js +0 -5
  27. package/dist/node_modules/.pnpm/react-use@17.6.0_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/react-use/esm/useCustomCompareEffect.js +0 -25
  28. package/dist/node_modules/.pnpm/react-use@17.6.0_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/react-use/esm/useDeepCompareEffect.js +0 -19
  29. package/dist/node_modules/.pnpm/react-use@17.6.0_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/react-use/esm/useFirstMountState.js +0 -12
  30. package/dist/node_modules/.pnpm/react-use@17.6.0_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/react-use/esm/useUpdateEffect.js +0 -13
@@ -2,8 +2,8 @@ import { JSX, Ref } from 'react';
2
2
  import { useVirtualizer, VirtualItem } from '@tanstack/react-virtual';
3
3
  import { ScrollViewRef } from './scroll-view';
4
4
  import { ShallowMerge } from '../types';
5
- type VirtualizedListOptions = Omit<Parameters<typeof useVirtualizer<HTMLDivElement, HTMLDivElement>>[0], 'getScrollElement'>;
6
- type VirtualizedListProps = ShallowMerge<JSX.IntrinsicElements['div'], {
5
+ type VirtualizedListOptions = Omit<Parameters<typeof useVirtualizer<HTMLDivElement, HTMLDivElement>>[0], "getScrollElement">;
6
+ type VirtualizedListProps = ShallowMerge<JSX.IntrinsicElements["div"], {
7
7
  RowComponent: React.ComponentType<{
8
8
  row: VirtualItem;
9
9
  }>;
@@ -1 +1 @@
1
- {"version":3,"file":"virtualized-list.d.ts","sourceRoot":"","sources":["../../src/components/virtualized-list.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,EAAE,GAAG,EAAU,MAAM,OAAO,CAAC;AAGzC,OAAO,EAAE,cAAc,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAC;AAGtE,OAAO,EAAc,aAAa,EAAE,MAAM,eAAe,CAAC;AAE1D,OAAO,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AAExC,KAAK,sBAAsB,GAAG,IAAI,CAChC,UAAU,CAAC,OAAO,cAAc,CAAC,cAAc,EAAE,cAAc,CAAC,CAAC,CAAC,CAAC,CAAC,EACpE,kBAAkB,CACnB,CAAC;AAEF,KAAK,oBAAoB,GAAG,YAAY,CACtC,GAAG,CAAC,iBAAiB,CAAC,KAAK,CAAC,EAC5B;IACE,YAAY,EAAE,KAAK,CAAC,aAAa,CAAC;QAAE,GAAG,EAAE,WAAW,CAAA;KAAE,CAAC,CAAC;IACxD,OAAO,EAAE,sBAAsB,CAAC;IAChC,GAAG,CAAC,EAAE,GAAG,CAAC,aAAa,CAAC,CAAC;CAC1B,CACF,CAAC;AAEF,YAAY,EAAE,WAAW,EAAE,oBAAoB,EAAE,sBAAsB,EAAE,CAAC;AAE1E,eAAO,MAAM,eAAe,6CAA8C,oBAAoB,qDAwC7F,CAAC"}
1
+ {"version":3,"file":"virtualized-list.d.ts","sourceRoot":"","sources":["../../src/components/virtualized-list.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,EAAE,GAAG,EAAU,MAAM,OAAO,CAAC;AAGzC,OAAO,EAAE,cAAc,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAC;AAGtE,OAAO,EAAc,aAAa,EAAE,MAAM,eAAe,CAAC;AAE1D,OAAO,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AAExC,KAAK,sBAAsB,GAAG,IAAI,CAChC,UAAU,CAAC,OAAO,cAAc,CAAC,cAAc,EAAE,cAAc,CAAC,CAAC,CAAC,CAAC,CAAC,EACpE,kBAAkB,CACnB,CAAC;AAEF,KAAK,oBAAoB,GAAG,YAAY,CACtC,GAAG,CAAC,iBAAiB,CAAC,KAAK,CAAC,EAC5B;IACE,YAAY,EAAE,KAAK,CAAC,aAAa,CAAC;QAAE,GAAG,EAAE,WAAW,CAAA;KAAE,CAAC,CAAC;IACxD,OAAO,EAAE,sBAAsB,CAAC;IAChC,GAAG,CAAC,EAAE,GAAG,CAAC,aAAa,CAAC,CAAC;CAC1B,CACF,CAAC;AAEF,YAAY,EAAE,WAAW,EAAE,oBAAoB,EAAE,sBAAsB,EAAE,CAAC;AAE1E,eAAO,MAAM,eAAe,6CAKzB,oBAAoB,qDAgDtB,CAAC"}
@@ -4,7 +4,12 @@ import { useMergeRefs } from "@floating-ui/react";
4
4
  import { useVirtualizer } from "@tanstack/react-virtual";
5
5
  import { motion } from "motion/react";
6
6
  import { ScrollView } from "./scroll-view.js";
7
- const VirtualizedList = ({ RowComponent, options, ref, ...props }) => {
7
+ const VirtualizedList = ({
8
+ RowComponent,
9
+ options,
10
+ ref,
11
+ ...props
12
+ }) => {
8
13
  var _a;
9
14
  const scrollRef = useRef(null);
10
15
  const mergedRefs = useMergeRefs([scrollRef, ref]);
@@ -32,7 +37,15 @@ const VirtualizedList = ({ RowComponent, options, ref, ...props }) => {
32
37
  style: {
33
38
  transform: `translateY(${((_a = items.at(0)) == null ? void 0 : _a.start) ?? 0}px)`
34
39
  },
35
- children: items.map((virtualRow) => /* @__PURE__ */ jsx("div", { "data-index": virtualRow.index, ref: virtualizer.measureElement, children: /* @__PURE__ */ jsx(RowComponent, { row: virtualRow }) }, virtualRow.key))
40
+ children: items.map((virtualRow) => /* @__PURE__ */ jsx(
41
+ "div",
42
+ {
43
+ "data-index": virtualRow.index,
44
+ ref: virtualizer.measureElement,
45
+ children: /* @__PURE__ */ jsx(RowComponent, { row: virtualRow })
46
+ },
47
+ virtualRow.key
48
+ ))
36
49
  }
37
50
  )
38
51
  }
@@ -6,4 +6,5 @@ export * from './use-countdown-timer';
6
6
  export * from './use-query-params';
7
7
  export * from './use-first-mount-state';
8
8
  export * from './use-update-effect';
9
+ export * from './use-deep-compare-effect';
9
10
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/hooks/index.ts"],"names":[],"mappings":"AAAA,cAAc,qBAAqB,CAAC;AACpC,cAAc,yBAAyB,CAAC;AACxC,cAAc,qBAAqB,CAAC;AACpC,cAAc,0BAA0B,CAAC;AACzC,cAAc,uBAAuB,CAAC;AACtC,cAAc,oBAAoB,CAAC;AACnC,cAAc,yBAAyB,CAAC;AACxC,cAAc,qBAAqB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/hooks/index.ts"],"names":[],"mappings":"AAAA,cAAc,qBAAqB,CAAC;AACpC,cAAc,yBAAyB,CAAC;AACxC,cAAc,qBAAqB,CAAC;AACpC,cAAc,0BAA0B,CAAC;AACzC,cAAc,uBAAuB,CAAC;AACtC,cAAc,oBAAoB,CAAC;AACnC,cAAc,yBAAyB,CAAC;AACxC,cAAc,qBAAqB,CAAC;AACpC,cAAc,2BAA2B,CAAC"}
@@ -6,9 +6,11 @@ import { useCountdownTimer } from "./use-countdown-timer.js";
6
6
  import { useQueryParams } from "./use-query-params.js";
7
7
  import { useFirstMountState } from "./use-first-mount-state/index.js";
8
8
  import { useUpdateEffect } from "./use-update-effect/index.js";
9
+ import { useDeepCompareEffect } from "./use-deep-compare-effect/index.js";
9
10
  export {
10
11
  useControllableState,
11
12
  useCountdownTimer,
13
+ useDeepCompareEffect,
12
14
  useFirstMountState,
13
15
  useHoverLineEffect,
14
16
  useQueryParams,
@@ -1,6 +1,6 @@
1
1
  import { useRef, useState, useMemo, useCallback } from "react";
2
2
  import { isUndefined, isEqual } from "lodash-es";
3
- import useUpdateEffect from "../node_modules/.pnpm/react-use@17.6.0_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/react-use/esm/useUpdateEffect.js";
3
+ import { useUpdateEffect } from "./use-update-effect/index.js";
4
4
  const getIsControlled = (value) => !isUndefined(value);
5
5
  const useControllableState = ({
6
6
  defaultValue,
@@ -1,6 +1,6 @@
1
1
  import { useRef, useState } from "react";
2
2
  import dayjs from "dayjs";
3
- import useDeepCompareEffect from "../node_modules/.pnpm/react-use@17.6.0_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/react-use/esm/useDeepCompareEffect.js";
3
+ import { useDeepCompareEffect } from "./use-deep-compare-effect/index.js";
4
4
  const getTimeDiff = (end, omit) => {
5
5
  const now = dayjs();
6
6
  const target = dayjs(end);
@@ -0,0 +1,3 @@
1
+ import { DependencyList, EffectCallback } from 'react';
2
+ export declare const useDeepCompareEffect: (effect: EffectCallback, deps: DependencyList) => void;
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/hooks/use-deep-compare-effect/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,cAAc,EAAqB,MAAM,OAAO,CAAC;AAc1E,eAAO,MAAM,oBAAoB,WACvB,cAAc,QAChB,cAAc,SAGrB,CAAC"}
@@ -0,0 +1,15 @@
1
+ import { useEffect, useRef } from "react";
2
+ import { isEqual } from "lodash-es";
3
+ function useDeepCompareMemoize(deps) {
4
+ const ref = useRef(deps);
5
+ if (!isEqual(deps, ref.current)) {
6
+ ref.current = deps;
7
+ }
8
+ return ref.current;
9
+ }
10
+ const useDeepCompareEffect = (effect, deps) => {
11
+ useEffect(effect, useDeepCompareMemoize(deps));
12
+ };
13
+ export {
14
+ useDeepCompareEffect
15
+ };
@@ -0,0 +1,30 @@
1
+ import { HTMLAttributes } from 'react';
2
+ import { CascaderOption } from './types';
3
+ import { InputProps } from '../input';
4
+ import { SizeVariant } from '../../types';
5
+ type CascaderFloatingContentProps = {
6
+ searchable: boolean;
7
+ selectedPath: string[];
8
+ options: CascaderOption[];
9
+ loadOptions?: (tree: CascaderOption[]) => Promise<CascaderOption[]>;
10
+ onChange?: (value: string[], selectedOptions: CascaderOption[]) => void;
11
+ inputProps?: InputProps;
12
+ listProps?: HTMLAttributes<HTMLDivElement>;
13
+ separator: React.ReactNode;
14
+ lazy: boolean;
15
+ xs?: {
16
+ size?: SizeVariant;
17
+ };
18
+ sm?: {
19
+ size?: SizeVariant;
20
+ };
21
+ md?: {
22
+ size?: SizeVariant;
23
+ };
24
+ lg?: {
25
+ size?: SizeVariant;
26
+ };
27
+ };
28
+ export declare const CascaderFloatingContent: ({ searchable, selectedPath, options, loadOptions, onChange, inputProps, listProps, separator, lazy, xs, sm, md, lg, }: CascaderFloatingContentProps) => import("@emotion/react/jsx-runtime").JSX.Element;
29
+ export {};
30
+ //# sourceMappingURL=cascader-floating-content.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cascader-floating-content.d.ts","sourceRoot":"","sources":["../../../src/lib/cascader/cascader-floating-content.tsx"],"names":[],"mappings":"AAAA,OAAO,EACL,cAAc,EAOf,MAAM,OAAO,CAAC;AAKf,OAAO,EAAE,cAAc,EAAE,MAAM,SAAS,CAAC;AAEzC,OAAO,EAAS,UAAU,EAAE,MAAM,UAAU,CAAC;AAe7C,OAAO,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AAMtC,KAAK,4BAA4B,GAAG;IAClC,UAAU,EAAE,OAAO,CAAC;IACpB,YAAY,EAAE,MAAM,EAAE,CAAC;IACvB,OAAO,EAAE,cAAc,EAAE,CAAC;IAC1B,WAAW,CAAC,EAAE,CAAC,IAAI,EAAE,cAAc,EAAE,KAAK,OAAO,CAAC,cAAc,EAAE,CAAC,CAAC;IACpE,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,EAAE,eAAe,EAAE,cAAc,EAAE,KAAK,IAAI,CAAC;IACxE,UAAU,CAAC,EAAE,UAAU,CAAC;IACxB,SAAS,CAAC,EAAE,cAAc,CAAC,cAAc,CAAC,CAAC;IAC3C,SAAS,EAAE,KAAK,CAAC,SAAS,CAAC;IAC3B,IAAI,EAAE,OAAO,CAAC;IACd,EAAE,CAAC,EAAE;QAAE,IAAI,CAAC,EAAE,WAAW,CAAA;KAAE,CAAC;IAC5B,EAAE,CAAC,EAAE;QAAE,IAAI,CAAC,EAAE,WAAW,CAAA;KAAE,CAAC;IAC5B,EAAE,CAAC,EAAE;QAAE,IAAI,CAAC,EAAE,WAAW,CAAA;KAAE,CAAC;IAC5B,EAAE,CAAC,EAAE;QAAE,IAAI,CAAC,EAAE,WAAW,CAAA;KAAE,CAAC;CAC7B,CAAC;AAEF,eAAO,MAAM,uBAAuB,0HAcjC,4BAA4B,qDA+b9B,CAAC"}
@@ -0,0 +1,411 @@
1
+ import { jsxs, jsx, Fragment } from "@emotion/react/jsx-runtime";
2
+ import { useRef, useId, useState, useEffect, useMemo, useCallback } from "react";
3
+ import { isString, isNil, trimStart } from "lodash-es";
4
+ import { findOptionPath, isExpandable, hasChildren } from "./helpers.js";
5
+ import ArrowRightIcon from "../../assets/svg/arrow-right.svg.js";
6
+ import CheckIcon from "../../assets/svg/done-check.svg.js";
7
+ import { SvgLoader } from "../../components/svg-loader.js";
8
+ import { VirtualizedList } from "../../components/virtualized-list.js";
9
+ import { getResponsiveProp, getSizeVariantState } from "../../utils/index.js";
10
+ import { useWindowScreen } from "../../hooks/use-window-screen/index.js";
11
+ import { useControllableState } from "../../hooks/use-controllable-state.js";
12
+ import { getColorVar } from "../../theme/palette.js";
13
+ import { getTypographyVar } from "../../theme/typography.js";
14
+ import { useFloatingContext } from "../floating/floating/helpers.js";
15
+ import { ensureArray, matchSearch } from "../../utils/common.js";
16
+ import { Input } from "../input/input.js";
17
+ import { TextSkeleton } from "../loading/text-skeleton/text-skeleton.js";
18
+ import { truncate } from "../../utils/emotion-helpers.js";
19
+ const DEFAULT_DISPLAY_ROW_COUNT = 5;
20
+ const CascaderFloatingContent = ({
21
+ searchable,
22
+ selectedPath,
23
+ options,
24
+ loadOptions,
25
+ onChange,
26
+ inputProps,
27
+ listProps,
28
+ separator,
29
+ lazy,
30
+ xs,
31
+ sm,
32
+ md,
33
+ lg
34
+ }) => {
35
+ const { context } = useFloatingContext();
36
+ const searchInputRef = useRef(null);
37
+ const uniqueId = useId();
38
+ const [inputValue, setInputValue] = useControllableState({
39
+ defaultValue: (inputProps == null ? void 0 : inputProps.defaultValue) ?? "",
40
+ value: inputProps == null ? void 0 : inputProps.value
41
+ });
42
+ const windowScreen = useWindowScreen();
43
+ const [expandedPath, setExpandedPath] = useState([]);
44
+ const [dynamicChildren, setDynamicChildren] = useState({});
45
+ const [isLoading, setIsLoading] = useState(false);
46
+ useEffect(() => {
47
+ if (selectedPath.length === 0) return;
48
+ const resolveExpandedPath = (fullPath, opts) => {
49
+ const pathOptions = findOptionPath(opts, fullPath);
50
+ const lastOption = pathOptions[pathOptions.length - 1];
51
+ if (lastOption && !isExpandable(lastOption)) {
52
+ return fullPath.slice(0, -1);
53
+ }
54
+ return fullPath;
55
+ };
56
+ if (!loadOptions) {
57
+ setExpandedPath(resolveExpandedPath(selectedPath, options));
58
+ return;
59
+ }
60
+ let cancelled = false;
61
+ const loadAlongPath = async () => {
62
+ var _a;
63
+ setIsLoading(true);
64
+ try {
65
+ let currentOpts = options;
66
+ const loadedChildren = {};
67
+ const pathSoFar = [];
68
+ const targetPath = resolveExpandedPath(selectedPath, options);
69
+ const existingPath = findOptionPath(options, targetPath);
70
+ if (existingPath.length === targetPath.length) {
71
+ if (!cancelled) setExpandedPath(targetPath);
72
+ return;
73
+ }
74
+ for (let i = 0; i < targetPath.length; i++) {
75
+ if (cancelled) return;
76
+ const value = targetPath[i];
77
+ const found = currentOpts.find((opt) => opt.value === value);
78
+ if (!found) break;
79
+ pathSoFar.push(found);
80
+ if (isExpandable(found) && !hasChildren(found)) {
81
+ const children = await loadOptions(pathSoFar);
82
+ if (cancelled) return;
83
+ const cacheKey = targetPath.slice(0, i + 1).join("/");
84
+ loadedChildren[cacheKey] = children;
85
+ currentOpts = children;
86
+ } else if ((_a = found.children) == null ? void 0 : _a.length) {
87
+ currentOpts = found.children;
88
+ } else {
89
+ break;
90
+ }
91
+ }
92
+ if (!cancelled) {
93
+ if (Object.keys(loadedChildren).length > 0) {
94
+ setDynamicChildren((prev) => ({ ...prev, ...loadedChildren }));
95
+ }
96
+ setExpandedPath(targetPath);
97
+ }
98
+ } finally {
99
+ if (!cancelled) setIsLoading(false);
100
+ }
101
+ };
102
+ loadAlongPath();
103
+ return () => {
104
+ cancelled = true;
105
+ };
106
+ }, []);
107
+ const mergedOptions = useMemo(() => {
108
+ if (!loadOptions || Object.keys(dynamicChildren).length === 0)
109
+ return options;
110
+ const mergeRecursive = (opts, parentKey) => {
111
+ return opts.map((opt) => {
112
+ const key = parentKey ? `${parentKey}/${opt.value}` : opt.value;
113
+ const loaded = dynamicChildren[key];
114
+ const children = loaded ?? opt.children;
115
+ return {
116
+ ...opt,
117
+ children: children ? mergeRecursive(children, key) : void 0
118
+ };
119
+ });
120
+ };
121
+ return mergeRecursive(options, "");
122
+ }, [options, dynamicChildren, loadOptions]);
123
+ const handleBreadcrumbClick = (e) => {
124
+ const level = Number(e.currentTarget.dataset.index);
125
+ if (level < 0) {
126
+ setExpandedPath([]);
127
+ } else {
128
+ setExpandedPath(expandedPath.slice(0, level + 1));
129
+ }
130
+ };
131
+ const expandedOptions = useMemo(() => {
132
+ return findOptionPath(mergedOptions, expandedPath);
133
+ }, [mergedOptions, expandedPath]);
134
+ const currentOptions = useMemo(() => {
135
+ var _a;
136
+ if (expandedPath.length === 0) {
137
+ return mergedOptions;
138
+ }
139
+ let current = mergedOptions;
140
+ for (const value of expandedPath) {
141
+ const found = current.find((opt) => opt.value === value);
142
+ if ((_a = found == null ? void 0 : found.children) == null ? void 0 : _a.length) {
143
+ current = found.children;
144
+ } else {
145
+ break;
146
+ }
147
+ }
148
+ return current;
149
+ }, [mergedOptions, expandedPath]);
150
+ const displayOptions = useMemo(() => {
151
+ if (!inputValue) {
152
+ return currentOptions;
153
+ }
154
+ return currentOptions.filter((option) => {
155
+ const searchLabels = ensureArray(option.searchLabel ?? []);
156
+ if (!searchLabels.length && isString(option.label)) {
157
+ searchLabels.push(option.label);
158
+ }
159
+ return matchSearch(searchLabels, inputValue);
160
+ });
161
+ }, [inputValue, currentOptions]);
162
+ const responsiveSize = isNil(windowScreen.name) ? void 0 : getResponsiveProp({ xs, sm, md, lg }, "size", windowScreen.name);
163
+ const { inputSize: rowMinHeight = 0, inputPaddingX } = getSizeVariantState(responsiveSize);
164
+ const onInputChange = (e) => {
165
+ var _a;
166
+ e.target.value = trimStart(e.target.value);
167
+ setInputValue(e.target.value);
168
+ (_a = inputProps == null ? void 0 : inputProps.onChange) == null ? void 0 : _a.call(inputProps, e);
169
+ };
170
+ useEffect(() => {
171
+ const timer = setTimeout(() => {
172
+ var _a;
173
+ (_a = searchInputRef.current) == null ? void 0 : _a.focus();
174
+ }, 100);
175
+ return () => clearTimeout(timer);
176
+ }, []);
177
+ const estimateSize = useCallback(
178
+ (_index) => {
179
+ return rowMinHeight ?? 0;
180
+ },
181
+ [rowMinHeight]
182
+ );
183
+ const getItemKey = useCallback(
184
+ (index) => {
185
+ const option = displayOptions.at(index);
186
+ return option ? option.value : `${uniqueId}-${index}`;
187
+ },
188
+ [displayOptions, uniqueId]
189
+ );
190
+ const renderBreadcrumbs = () => {
191
+ if (expandedPath.length === 0) return null;
192
+ return /* @__PURE__ */ jsxs(
193
+ "div",
194
+ {
195
+ css: {
196
+ paddingLeft: inputPaddingX,
197
+ paddingRight: inputPaddingX,
198
+ minHeight: rowMinHeight,
199
+ borderTop: `1px solid ${getColorVar("neutral.200")}`,
200
+ display: "flex",
201
+ alignItems: "center",
202
+ gap: "0.25rem",
203
+ flexWrap: "wrap",
204
+ paddingTop: "0.25rem",
205
+ paddingBottom: "0.25rem"
206
+ },
207
+ children: [
208
+ /* @__PURE__ */ jsx(
209
+ "button",
210
+ {
211
+ "data-index": -1,
212
+ type: "button",
213
+ onClick: handleBreadcrumbClick,
214
+ css: {
215
+ color: getColorVar("neutral.500"),
216
+ transition: "color 150ms",
217
+ "&:hover": { color: getColorVar("primary.600") }
218
+ },
219
+ children: "All"
220
+ }
221
+ ),
222
+ expandedOptions.map((opt, idx) => /* @__PURE__ */ jsxs(
223
+ "div",
224
+ {
225
+ css: { display: "flex", alignItems: "center", gap: "0.25rem" },
226
+ children: [
227
+ /* @__PURE__ */ jsx("span", { css: { color: getColorVar("neutral.400") }, children: separator }),
228
+ /* @__PURE__ */ jsx(
229
+ "button",
230
+ {
231
+ "data-index": idx,
232
+ type: "button",
233
+ onClick: handleBreadcrumbClick,
234
+ css: {
235
+ color: idx === expandedOptions.length - 1 ? getColorVar("primary.600") : getColorVar("neutral.600"),
236
+ fontWeight: idx === expandedOptions.length - 1 ? 500 : void 0,
237
+ transition: "color 150ms",
238
+ "&:hover": { color: getColorVar("primary.600") }
239
+ },
240
+ children: opt.breadcrumbLabel ?? opt.label
241
+ }
242
+ )
243
+ ]
244
+ },
245
+ `${uniqueId}-breadcrumb-${opt.value}`
246
+ ))
247
+ ]
248
+ }
249
+ );
250
+ };
251
+ const RowComponent = ({ row }) => {
252
+ const rowData = displayOptions.at(row.index);
253
+ if (isNil(rowData)) return /* @__PURE__ */ jsx(Fragment, {});
254
+ const isSelected = selectedPath.includes(rowData.value);
255
+ const handleSelect = async () => {
256
+ var _a, _b;
257
+ if (rowData.disabled || isLoading) return;
258
+ const parentPath = [];
259
+ let current = mergedOptions;
260
+ for (const value of expandedPath) {
261
+ const found = current.find((opt) => opt.value === value);
262
+ if ((_a = found == null ? void 0 : found.children) == null ? void 0 : _a.length) {
263
+ parentPath.push(value);
264
+ current = found.children;
265
+ } else {
266
+ break;
267
+ }
268
+ }
269
+ const newPath = [...parentPath, rowData.value];
270
+ const newSelectedOptions = findOptionPath(mergedOptions, newPath);
271
+ if (isExpandable(rowData)) {
272
+ if (!hasChildren(rowData) && loadOptions) {
273
+ const cacheKey = newPath.join("/");
274
+ setIsLoading(true);
275
+ try {
276
+ const children = await loadOptions(newSelectedOptions);
277
+ setDynamicChildren((prev) => ({ ...prev, [cacheKey]: children }));
278
+ setExpandedPath(newPath);
279
+ } finally {
280
+ setIsLoading(false);
281
+ }
282
+ } else {
283
+ setExpandedPath(newPath);
284
+ }
285
+ } else {
286
+ onChange == null ? void 0 : onChange(newPath, newSelectedOptions);
287
+ (_b = context.onOpenChange) == null ? void 0 : _b.call(context, false);
288
+ }
289
+ setInputValue("");
290
+ setTimeout(() => {
291
+ var _a2;
292
+ (_a2 = searchInputRef.current) == null ? void 0 : _a2.focus();
293
+ });
294
+ };
295
+ return /* @__PURE__ */ jsx(
296
+ "div",
297
+ {
298
+ "aria-hidden": true,
299
+ role: "button",
300
+ onClick: handleSelect,
301
+ css: {
302
+ minHeight: rowMinHeight,
303
+ paddingLeft: inputPaddingX,
304
+ paddingRight: inputPaddingX,
305
+ paddingTop: "0.25rem",
306
+ paddingBottom: "0.25rem",
307
+ display: "flex",
308
+ alignItems: "center",
309
+ gap: "0.5rem",
310
+ borderRadius: "0.5rem",
311
+ transition: "background-color 150ms, color 150ms",
312
+ "&:hover": { backgroundColor: getColorVar("neutral.100") },
313
+ ...isSelected && !isExpandable(rowData) ? {
314
+ color: getColorVar("primary.600"),
315
+ backgroundColor: getColorVar("primary.100")
316
+ } : {},
317
+ ...rowData.disabled ? { opacity: 0.5, cursor: "not-allowed" } : {}
318
+ },
319
+ children: isLoading ? /* @__PURE__ */ jsx(TextSkeleton, {}) : /* @__PURE__ */ jsxs(Fragment, { children: [
320
+ /* @__PURE__ */ jsx("div", { css: { flex: 1, ...truncate }, children: rowData.label }),
321
+ isExpandable(rowData) ? /* @__PURE__ */ jsx(
322
+ SvgLoader,
323
+ {
324
+ source: ArrowRightIcon,
325
+ width: 20,
326
+ height: 20,
327
+ css: { color: getColorVar("neutral.400") }
328
+ }
329
+ ) : isSelected && /* @__PURE__ */ jsx(
330
+ SvgLoader,
331
+ {
332
+ source: CheckIcon,
333
+ width: 20,
334
+ height: 20,
335
+ css: { color: getColorVar("primary.600") }
336
+ }
337
+ )
338
+ ] })
339
+ },
340
+ `${uniqueId}-option-${rowData.value}`
341
+ );
342
+ };
343
+ return /* @__PURE__ */ jsxs(
344
+ "div",
345
+ {
346
+ css: {
347
+ paddingTop: "0.5rem",
348
+ paddingBottom: "0.5rem",
349
+ border: `1px solid ${getColorVar("border.default")}`,
350
+ borderRadius: "0.5rem",
351
+ boxShadow: "0 1px 3px 0 rgb(0 0 0 / 0.1), 0 1px 2px -1px rgb(0 0 0 / 0.1)",
352
+ fontSize: getTypographyVar("sm").fontSize,
353
+ lineHeight: getTypographyVar("sm").lineHeight,
354
+ backgroundColor: getColorVar("surface.default")
355
+ },
356
+ children: [
357
+ !searchable && /* @__PURE__ */ jsx(
358
+ "div",
359
+ {
360
+ css: {
361
+ paddingLeft: "0.5rem",
362
+ paddingRight: "0.5rem",
363
+ paddingTop: "0.5rem",
364
+ paddingBottom: "0.5rem"
365
+ },
366
+ children: /* @__PURE__ */ jsx(
367
+ Input,
368
+ {
369
+ xs: { size: xs == null ? void 0 : xs.size },
370
+ sm: { size: sm == null ? void 0 : sm.size },
371
+ md: { size: md == null ? void 0 : md.size },
372
+ lg: { size: lg == null ? void 0 : lg.size },
373
+ value: inputValue,
374
+ placeholder: "Search...",
375
+ ...inputProps,
376
+ onChange: onInputChange,
377
+ ref: searchInputRef
378
+ }
379
+ )
380
+ }
381
+ ),
382
+ /* @__PURE__ */ jsx(
383
+ VirtualizedList,
384
+ {
385
+ ...listProps,
386
+ css: {
387
+ paddingLeft: 4,
388
+ paddingRight: 4,
389
+ ...isLoading ? { cursor: "wait", pointerEvents: "none" } : {}
390
+ },
391
+ options: {
392
+ count: 2,
393
+ estimateSize,
394
+ getItemKey,
395
+ overscan: lazy ? void 0 : currentOptions.length
396
+ },
397
+ style: {
398
+ maxHeight: rowMinHeight * DEFAULT_DISPLAY_ROW_COUNT,
399
+ ...listProps == null ? void 0 : listProps.style
400
+ },
401
+ RowComponent
402
+ }
403
+ ),
404
+ renderBreadcrumbs()
405
+ ]
406
+ }
407
+ );
408
+ };
409
+ export {
410
+ CascaderFloatingContent
411
+ };
@@ -1,3 +1,3 @@
1
- import { CascaderOption, CascaderOptionValue, CascaderProps } from './types';
2
- export declare const Cascader: <V extends CascaderOptionValue = CascaderOptionValue, O extends CascaderOption<V> = CascaderOption<V>>({ ref, ..._props }: CascaderProps<V, O>) => import("@emotion/react/jsx-runtime").JSX.Element;
1
+ import { CascaderProps } from './types';
2
+ export declare const Cascader: ({ ref, ..._props }: CascaderProps) => import("@emotion/react/jsx-runtime").JSX.Element;
3
3
  //# sourceMappingURL=cascader.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"cascader.d.ts","sourceRoot":"","sources":["../../../src/lib/cascader/cascader.tsx"],"names":[],"mappings":"AAeA,OAAO,EAAE,cAAc,EAAE,mBAAmB,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AA2B7E,eAAO,MAAM,QAAQ,GACnB,CAAC,SAAS,mBAAmB,wBAC7B,CAAC,SAAS,cAAc,CAAC,CAAC,CAAC,0CAI1B,aAAa,CAAC,CAAC,EAAE,CAAC,CAAC,qDAigBrB,CAAC"}
1
+ {"version":3,"file":"cascader.d.ts","sourceRoot":"","sources":["../../../src/lib/cascader/cascader.tsx"],"names":[],"mappings":"AAQA,OAAO,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAqBxC,eAAO,MAAM,QAAQ,uBAAwB,aAAa,qDAuJzD,CAAC"}