@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
@@ -1,42 +1,36 @@
1
- import { jsxs, jsx, Fragment } from "@emotion/react/jsx-runtime";
2
- import { useRef, useId, useState, useMemo, useEffect, useCallback } from "react";
3
- import { isString, isNil, trimStart } from "lodash-es";
4
- import { getCascaderProps, findOptionPath, hasChildren } from "./helpers.js";
5
- import { SvgLoader } from "../../components/svg-loader.js";
6
- import { VirtualizedList } from "../../components/virtualized-list.js";
7
- import { useWindowScreen } from "../../hooks/use-window-screen/index.js";
8
- import { useControllableState } from "../../hooks/use-controllable-state.js";
9
- import { getResponsiveProp, getSizeVariantState } from "../../utils/index.js";
1
+ import { jsxs, jsx } from "@emotion/react/jsx-runtime";
2
+ import { useRef } from "react";
3
+ import { isNil } from "lodash-es";
4
+ import { CascaderFloatingContent } from "./cascader-floating-content.js";
5
+ import { getCascaderProps } from "./helpers.js";
10
6
  import ArrowDownIcon from "../../assets/svg/arrow-down.svg.js";
11
- import ArrowRightIcon from "../../assets/svg/arrow-right.svg.js";
12
- import CheckIcon from "../../assets/svg/done-check.svg.js";
13
7
  import { getColorVar } from "../../theme/palette.js";
14
8
  import { getTypographyVar } from "../../theme/typography.js";
15
- import { ensureArray, matchSearch } from "../../utils/common.js";
9
+ import { getSizeVariantState } from "../../utils/index.js";
10
+ import { useControllableState } from "../../hooks/use-controllable-state.js";
11
+ import { SvgLoader } from "../../components/svg-loader.js";
12
+ import { Primitive } from "../primitive/primitive.js";
16
13
  import { Floating } from "../floating/floating/floating.js";
17
14
  import { FloatingTrigger } from "../floating/floating-trigger/floating-trigger.js";
18
15
  import { InputMask as ForwardRefInputMask } from "../input-mask/input-mask.js";
16
+ import { truncate } from "../../utils/emotion-helpers.js";
19
17
  import { FloatingContent } from "../floating/floating-content/floating-content.js";
20
- import { Input } from "../input/input.js";
21
18
  import { FormHelperText } from "../form-helper-text/form-helper-text.js";
22
19
  const DEFAULT_SEPARATOR = "/";
23
- const DEFAULT_DISPLAY_ROW_COUNT = 5;
24
- const Cascader = ({
25
- ref,
26
- ..._props
27
- }) => {
28
- var _a, _b, _c, _d, _e;
20
+ const Cascader = ({ ref, ..._props }) => {
21
+ var _a;
29
22
  const {
30
23
  placement = "bottom-start",
31
24
  open,
32
25
  onOpenChange,
33
26
  searchable = false,
34
27
  value: selectedPath = [],
28
+ valueRenderer,
35
29
  options,
30
+ loadOptions,
36
31
  onChange,
37
32
  placeholder,
38
33
  listProps,
39
- selectedRenderer,
40
34
  separator = DEFAULT_SEPARATOR,
41
35
  helperText,
42
36
  error,
@@ -47,70 +41,15 @@ const Cascader = ({
47
41
  menuWidth = "exact-reference",
48
42
  ...rest
49
43
  } = getCascaderProps(_props);
50
- const searchInputRef = useRef(null);
51
44
  const floatingRef = useRef(null);
52
- const uniqueId = useId();
53
- const [inputValue, setInputValue] = useControllableState({
54
- defaultValue: (inputProps == null ? void 0 : inputProps.defaultValue) ?? "",
55
- value: inputProps == null ? void 0 : inputProps.value
56
- });
57
- const windowScreen = useWindowScreen();
58
45
  const [isOpen, setIsOpen] = useControllableState({
59
46
  defaultValue: open ?? false,
60
47
  value: open
61
48
  });
62
- const [expandedPath, setExpandedPath] = useState([]);
63
49
  const handleOpenChange = (nextOpen, event, reason) => {
64
50
  setIsOpen(nextOpen);
65
51
  onOpenChange == null ? void 0 : onOpenChange(nextOpen, event, reason);
66
- if (!nextOpen) {
67
- setExpandedPath(selectedPath);
68
- }
69
- };
70
- const handleBreadcrumbClick = (e) => {
71
- const level = Number(e.currentTarget.dataset.index);
72
- if (level < 0) {
73
- setExpandedPath([]);
74
- } else {
75
- setExpandedPath(expandedPath.slice(0, level + 1));
76
- }
77
52
  };
78
- const selectedOptions = useMemo(() => {
79
- return findOptionPath(options, selectedPath);
80
- }, [options, selectedPath]);
81
- const expandedOptions = useMemo(() => {
82
- return findOptionPath(options, expandedPath);
83
- }, [options, expandedPath]);
84
- const currentOptions = useMemo(() => {
85
- var _a2;
86
- if (expandedPath.length === 0) {
87
- return options;
88
- }
89
- let current = options;
90
- for (const value of expandedPath) {
91
- const found = current.find((opt) => opt.value === value);
92
- if ((_a2 = found == null ? void 0 : found.children) == null ? void 0 : _a2.length) {
93
- current = found.children;
94
- } else {
95
- break;
96
- }
97
- }
98
- return current;
99
- }, [options, expandedPath]);
100
- const displayOptions = useMemo(() => {
101
- if (!inputValue) {
102
- return currentOptions;
103
- }
104
- return currentOptions.filter((option) => {
105
- const searchLabels = ensureArray(option.searchLabel ?? []);
106
- if (!searchLabels.length && isString(option.label)) {
107
- searchLabels.push(option.label);
108
- }
109
- return matchSearch(searchLabels, inputValue);
110
- });
111
- }, [inputValue, currentOptions]);
112
- const responsiveSize = isNil(windowScreen.name) ? void 0 : getResponsiveProp(rest, "size", windowScreen.name);
113
- const { inputSize: rowMinHeight = 0, inputPaddingX } = getSizeVariantState(responsiveSize);
114
53
  const sizeOptions = {
115
54
  apply({ elements }) {
116
55
  const { width } = elements.reference.getBoundingClientRect();
@@ -135,215 +74,8 @@ const Cascader = ({
135
74
  if (isNil(textVariant)) return {};
136
75
  return getTypographyVar(textVariant);
137
76
  };
138
- const onInputChange = (e) => {
139
- var _a2;
140
- e.target.value = trimStart(e.target.value);
141
- setInputValue(e.target.value);
142
- (_a2 = inputProps == null ? void 0 : inputProps.onChange) == null ? void 0 : _a2.call(inputProps, e);
143
- };
144
- const displayValue = useMemo(() => {
145
- if (selectedOptions.length === 0) return null;
146
- if (selectedRenderer) {
147
- return selectedRenderer(selectedOptions);
148
- }
149
- return selectedOptions.map((opt, idx) => /* @__PURE__ */ jsxs(
150
- "div",
151
- {
152
- css: { display: "flex", alignItems: "center" },
153
- children: [
154
- opt.label,
155
- idx < selectedOptions.length - 1 && /* @__PURE__ */ jsx("span", { css: { marginLeft: 4, marginRight: 4, opacity: 0.6 }, children: separator })
156
- ]
157
- },
158
- `${uniqueId}-${opt.value}`
159
- ));
160
- }, [selectedOptions, selectedRenderer, separator, uniqueId]);
161
- useEffect(() => {
162
- const timer = setTimeout(() => {
163
- var _a2;
164
- if (isOpen) {
165
- (_a2 = searchInputRef.current) == null ? void 0 : _a2.focus();
166
- setExpandedPath(selectedPath);
167
- } else {
168
- setInputValue("");
169
- }
170
- }, 100);
171
- return () => clearTimeout(timer);
172
- }, [isOpen]);
173
- const estimateSize = useCallback(
174
- (_index) => {
175
- return rowMinHeight ?? 0;
176
- },
177
- [rowMinHeight]
178
- );
179
- const getItemKey = useCallback(
180
- (index) => {
181
- const option = displayOptions.at(index);
182
- return option ? option.value : `${uniqueId}-${index}`;
183
- },
184
- [displayOptions, uniqueId]
185
- );
186
- const renderBreadcrumbs = () => {
187
- if (expandedPath.length === 0) return null;
188
- return /* @__PURE__ */ jsxs(
189
- "div",
190
- {
191
- css: {
192
- paddingLeft: inputPaddingX,
193
- paddingRight: inputPaddingX,
194
- minHeight: rowMinHeight,
195
- borderTop: "1px solid",
196
- borderColor: getColorVar("neutral.200"),
197
- display: "flex",
198
- alignItems: "center",
199
- gap: 4,
200
- flexWrap: "wrap",
201
- paddingTop: 4,
202
- paddingBottom: 4
203
- },
204
- children: [
205
- /* @__PURE__ */ jsx(
206
- "button",
207
- {
208
- "data-index": -1,
209
- type: "button",
210
- onClick: handleBreadcrumbClick,
211
- css: {
212
- color: getColorVar("neutral.500"),
213
- ":hover": { color: getColorVar("primary.600") },
214
- transition: "color 150ms"
215
- },
216
- children: "All"
217
- }
218
- ),
219
- expandedOptions.map((opt, idx) => /* @__PURE__ */ jsxs(
220
- "div",
221
- {
222
- css: { display: "flex", alignItems: "center", gap: 4 },
223
- children: [
224
- /* @__PURE__ */ jsx("span", { css: { color: getColorVar("neutral.400") }, children: separator }),
225
- /* @__PURE__ */ jsx(
226
- "button",
227
- {
228
- "data-index": idx,
229
- type: "button",
230
- onClick: handleBreadcrumbClick,
231
- css: {
232
- color: getColorVar("neutral.600"),
233
- ":hover": { color: getColorVar("primary.600") },
234
- transition: "color 150ms",
235
- ...idx === expandedOptions.length - 1 ? {
236
- color: getColorVar("primary.600"),
237
- fontWeight: 500
238
- } : {}
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 = () => {
256
- var _a2, _b2, _c2, _d2;
257
- if (rowData.disabled) return;
258
- const parentPath = [];
259
- let current = options;
260
- for (const value of expandedPath) {
261
- const found = current.find((opt) => opt.value === value);
262
- if ((_a2 = found == null ? void 0 : found.children) == null ? void 0 : _a2.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(options, newPath);
271
- if (hasChildren(rowData)) {
272
- setExpandedPath(newPath);
273
- } else {
274
- onChange == null ? void 0 : onChange(newPath, newSelectedOptions);
275
- (_d2 = (_b2 = floatingRef.current) == null ? void 0 : (_c2 = _b2.context).onOpenChange) == null ? void 0 : _d2.call(_c2, false);
276
- }
277
- setInputValue("");
278
- setTimeout(() => {
279
- var _a3;
280
- (_a3 = searchInputRef.current) == null ? void 0 : _a3.focus();
281
- });
282
- };
283
- return /* @__PURE__ */ jsxs(
284
- "div",
285
- {
286
- "aria-hidden": true,
287
- onClick: handleSelect,
288
- css: {
289
- minHeight: rowMinHeight,
290
- paddingLeft: inputPaddingX,
291
- paddingRight: inputPaddingX,
292
- paddingTop: 4,
293
- paddingBottom: 4,
294
- display: "flex",
295
- alignItems: "center",
296
- gap: 8,
297
- cursor: "pointer",
298
- borderRadius: 8,
299
- ":hover": { backgroundColor: getColorVar("neutral.100") },
300
- transition: "color 150ms, background-color 150ms",
301
- ...isSelected && !hasChildren(rowData) ? {
302
- color: getColorVar("primary.600"),
303
- backgroundColor: getColorVar("primary.100")
304
- } : {},
305
- ...rowData.disabled ? {
306
- opacity: 0.5,
307
- cursor: "not-allowed"
308
- } : {}
309
- },
310
- children: [
311
- /* @__PURE__ */ jsx(
312
- "div",
313
- {
314
- css: {
315
- flex: 1,
316
- overflow: "hidden",
317
- textOverflow: "ellipsis",
318
- whiteSpace: "nowrap"
319
- },
320
- children: rowData.label
321
- }
322
- ),
323
- hasChildren(rowData) ? /* @__PURE__ */ jsx(
324
- SvgLoader,
325
- {
326
- source: ArrowRightIcon,
327
- width: 20,
328
- height: 20,
329
- css: { color: getColorVar("neutral.400") }
330
- }
331
- ) : isSelected && /* @__PURE__ */ jsx(
332
- SvgLoader,
333
- {
334
- source: CheckIcon,
335
- width: 20,
336
- height: 20,
337
- css: { color: getColorVar("primary.600") }
338
- }
339
- )
340
- ]
341
- },
342
- `${uniqueId}-option-${rowData.value}`
343
- );
344
- };
345
77
  return /* @__PURE__ */ jsxs(
346
- "div",
78
+ Primitive,
347
79
  {
348
80
  ...containerProps,
349
81
  css: {
@@ -351,6 +83,7 @@ const Cascader = ({
351
83
  flexDirection: "column",
352
84
  ...fullWidth ? { width: "100%" } : {}
353
85
  },
86
+ as: "div",
354
87
  children: [
355
88
  /* @__PURE__ */ jsxs(
356
89
  Floating,
@@ -394,94 +127,31 @@ const Cascader = ({
394
127
  {
395
128
  flex: 1,
396
129
  textAlign: "left",
397
- overflow: "hidden",
398
- textOverflow: "ellipsis",
399
- whiteSpace: "nowrap"
130
+ ...truncate
400
131
  },
401
132
  getTextCss((_a = rest.xs) == null ? void 0 : _a.size)
402
133
  ],
403
- children: displayValue ? /* @__PURE__ */ jsx(
404
- "div",
405
- {
406
- css: {
407
- display: "flex",
408
- alignItems: "center",
409
- flexWrap: "wrap"
410
- },
411
- children: displayValue
412
- }
413
- ) : /* @__PURE__ */ jsx(
414
- "span",
415
- {
416
- css: { color: getColorVar("neutral.400"), display: "block" },
417
- children: placeholder
418
- }
419
- )
134
+ children: selectedPath.length > 0 ? /* @__PURE__ */ jsx("div", { children: valueRenderer ?? selectedPath.join(" / ") }) : /* @__PURE__ */ jsx("div", { css: { color: getColorVar("neutral.400") }, children: placeholder })
420
135
  }
421
136
  )
422
137
  }
423
138
  ) }),
424
- /* @__PURE__ */ jsx(FloatingContent, { children: /* @__PURE__ */ jsxs(
425
- "div",
139
+ /* @__PURE__ */ jsx(FloatingContent, { children: /* @__PURE__ */ jsx(
140
+ CascaderFloatingContent,
426
141
  {
427
- css: {
428
- paddingTop: 8,
429
- paddingBottom: 8,
430
- border: "1px solid",
431
- borderColor: getColorVar("border.default"),
432
- borderRadius: 8,
433
- boxShadow: "0 1px 3px 0 rgb(0 0 0 / 0.1), 0 1px 2px -1px rgb(0 0 0 / 0.1)",
434
- fontSize: "0.875rem",
435
- lineHeight: "1.25rem",
436
- backgroundColor: getColorVar("surface.default")
437
- },
438
- children: [
439
- !searchable && /* @__PURE__ */ jsx(
440
- "div",
441
- {
442
- css: {
443
- paddingLeft: 8,
444
- paddingRight: 8,
445
- paddingTop: 8,
446
- paddingBottom: 8,
447
- borderColor: getColorVar("neutral.200")
448
- },
449
- children: /* @__PURE__ */ jsx(
450
- Input,
451
- {
452
- xs: { size: (_b = rest.xs) == null ? void 0 : _b.size },
453
- sm: { size: (_c = rest.sm) == null ? void 0 : _c.size },
454
- md: { size: (_d = rest.md) == null ? void 0 : _d.size },
455
- lg: { size: (_e = rest.lg) == null ? void 0 : _e.size },
456
- value: inputValue,
457
- placeholder: "Search...",
458
- ...inputProps,
459
- onChange: onInputChange,
460
- ref: searchInputRef
461
- }
462
- )
463
- }
464
- ),
465
- /* @__PURE__ */ jsx(
466
- VirtualizedList,
467
- {
468
- ...listProps,
469
- css: { paddingLeft: 4, paddingRight: 4 },
470
- options: {
471
- count: displayOptions.length,
472
- estimateSize,
473
- getItemKey,
474
- overscan: lazy ? void 0 : currentOptions.length
475
- },
476
- style: {
477
- maxHeight: rowMinHeight * DEFAULT_DISPLAY_ROW_COUNT,
478
- ...listProps == null ? void 0 : listProps.style
479
- },
480
- RowComponent
481
- }
482
- ),
483
- renderBreadcrumbs()
484
- ]
142
+ searchable,
143
+ selectedPath,
144
+ options,
145
+ loadOptions,
146
+ onChange,
147
+ inputProps,
148
+ listProps,
149
+ separator,
150
+ lazy,
151
+ xs: rest.xs,
152
+ sm: rest.sm,
153
+ md: rest.md,
154
+ lg: rest.lg
485
155
  }
486
156
  ) })
487
157
  ]
@@ -1,16 +1,20 @@
1
- import { CascaderOption, CascaderOptionValue, CascaderProps } from './types';
2
- export declare const getCascaderProps: <V extends CascaderOptionValue = CascaderOptionValue, O extends CascaderOption<V> = CascaderOption<V>>(extended: CascaderProps<V, O>) => CascaderProps<V, O>;
1
+ import { CascaderOption, CascaderProps } from './types';
2
+ export declare const getCascaderProps: (extended: CascaderProps) => CascaderProps;
3
3
  /**
4
4
  * Find option path by value array
5
5
  * Returns array of options from root to target
6
6
  */
7
- export declare const findOptionPath: <V extends CascaderOptionValue, O extends CascaderOption<V>>(options: O[], values: V[]) => O[];
7
+ export declare const findOptionPath: (options: CascaderOption[], values: string[]) => CascaderOption[];
8
8
  /**
9
- * Check if option has children
9
+ * Check if option has children already loaded
10
10
  */
11
- export declare const hasChildren: <V extends CascaderOptionValue, O extends CascaderOption<V>>(option: O) => boolean;
11
+ export declare const hasChildren: (option: CascaderOption) => boolean;
12
+ /**
13
+ * Check if option can be expanded (has children or is not a leaf and can lazy load)
14
+ */
15
+ export declare const isExpandable: (option: CascaderOption) => boolean;
12
16
  /**
13
17
  * Filter options by search text
14
18
  */
15
- export declare const filterOptions: <V extends CascaderOptionValue, O extends CascaderOption<V>>(options: O[], searchText: string) => O[];
19
+ export declare const filterOptions: (options: CascaderOption[], searchText: string) => CascaderOption[];
16
20
  //# sourceMappingURL=helpers.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"helpers.d.ts","sourceRoot":"","sources":["../../../src/lib/cascader/helpers.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,mBAAmB,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAU7E,eAAO,MAAM,gBAAgB,GAC3B,CAAC,SAAS,mBAAmB,wBAC7B,CAAC,SAAS,cAAc,CAAC,CAAC,CAAC,gCAEjB,aAAa,CAAC,CAAC,EAAE,CAAC,CAAC,wBAG9B,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,cAAc,GAAI,CAAC,SAAS,mBAAmB,EAAE,CAAC,SAAS,cAAc,CAAC,CAAC,CAAC,WAC9E,CAAC,EAAE,UACJ,CAAC,EAAE,KACV,CAAC,EAYH,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,WAAW,GAAI,CAAC,SAAS,mBAAmB,EAAE,CAAC,SAAS,cAAc,CAAC,CAAC,CAAC,UAAU,CAAC,KAAG,OAEnG,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,aAAa,GAAI,CAAC,SAAS,mBAAmB,EAAE,CAAC,SAAS,cAAc,CAAC,CAAC,CAAC,WAC7E,CAAC,EAAE,cACA,MAAM,KACjB,CAAC,EA2BH,CAAC"}
1
+ {"version":3,"file":"helpers.d.ts","sourceRoot":"","sources":["../../../src/lib/cascader/helpers.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAUxD,eAAO,MAAM,gBAAgB,aAAc,aAAa,kBAEvD,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,cAAc,YAAa,cAAc,EAAE,UAAU,MAAM,EAAE,KAAG,cAAc,EAY1F,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,WAAW,WAAY,cAAc,KAAG,OAEpD,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,YAAY,WAAY,cAAc,KAAG,OAKrD,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,aAAa,YAAa,cAAc,EAAE,cAAc,MAAM,KAAG,cAAc,EA2B3F,CAAC"}
@@ -14,15 +14,21 @@ const findOptionPath = (options, values) => {
14
14
  const found = currentOptions.find((opt) => opt.value === value);
15
15
  if (!found) break;
16
16
  result.push(found);
17
- currentOptions = found.children || [];
17
+ currentOptions = found.children ?? [];
18
18
  }
19
19
  return result;
20
20
  };
21
21
  const hasChildren = (option) => {
22
22
  return Array.isArray(option.children) && option.children.length > 0;
23
23
  };
24
+ const isExpandable = (option) => {
25
+ if (option.isLeaf === true) return false;
26
+ if (hasChildren(option)) return true;
27
+ return option.isLeaf === false;
28
+ };
24
29
  export {
25
30
  findOptionPath,
26
31
  getCascaderProps,
27
- hasChildren
32
+ hasChildren,
33
+ isExpandable
28
34
  };
@@ -1,20 +1,24 @@
1
- import { HTMLAttributes, JSX } from 'react';
1
+ import { HTMLAttributes, JSX, ReactNode } from 'react';
2
2
  import { Placement, UseFloatingOptions } from '@floating-ui/react';
3
+ import { ResponsiveDesign } from '@janbox/storefront-ui/types';
3
4
  import { InputProps } from '../input';
4
5
  import { InputMaskProps, InputMaskResponsiveProps } from '../input-mask/types';
5
- import { ResponsiveDesign, ShallowMerge } from '../../types';
6
+ import { ShallowMerge } from '../../types';
6
7
  import { PrimitiveProps } from '../primitive';
7
8
  export type CascaderResponsiveProps = InputMaskResponsiveProps;
8
9
  export type CascaderOptionValue = string | number;
9
- export interface CascaderOption<V extends CascaderOptionValue = CascaderOptionValue> {
10
- value: V;
10
+ export interface CascaderOption {
11
+ metadata?: Record<string, any>;
12
+ value: string;
11
13
  label: React.ReactNode;
12
14
  breadcrumbLabel?: React.ReactNode;
13
15
  searchLabel?: string | string[];
14
16
  disabled?: boolean;
15
- children?: CascaderOption<V>[];
17
+ children?: CascaderOption[];
18
+ /** When true, this option is a leaf node and cannot be expanded. When false, it can be expanded even without children loaded yet. */
19
+ isLeaf?: boolean;
16
20
  }
17
- interface CascaderExtendedProps<V extends CascaderOptionValue, O extends CascaderOption<V>> extends ResponsiveDesign<CascaderResponsiveProps> {
21
+ interface CascaderExtendedProps extends ResponsiveDesign<CascaderResponsiveProps> {
18
22
  /** Placement of the dropdown */
19
23
  placement?: Placement;
20
24
  /** Callback when dropdown open state changes */
@@ -25,17 +29,19 @@ interface CascaderExtendedProps<V extends CascaderOptionValue, O extends Cascade
25
29
  searchable?: boolean;
26
30
  /** Default selected path (array of values from root to leaf) */
27
31
  /** Controlled selected path */
28
- value?: V[];
32
+ value?: string[];
33
+ valueRenderer?: ReactNode;
29
34
  /** Tree options data */
30
- options: O[];
35
+ options: CascaderOption[];
36
+ /** Async function to load children. Receives the current expanded path as an array of selected options from root to the clicked node. */
37
+ loadOptions?: (tree: CascaderOption[]) => Promise<CascaderOption[]>;
31
38
  /** Callback when selection changes */
32
- onChange?: (value: V[], selectedOptions: O[]) => void;
39
+ onChange?: (value: string[], selectedOptions: CascaderOption[]) => void;
33
40
  /** Placeholder text */
34
41
  placeholder?: string;
35
42
  /** Props for the options list container */
36
43
  listProps?: HTMLAttributes<HTMLDivElement>;
37
44
  /** Custom renderer for selected value display */
38
- selectedRenderer?: (selectedOptions: O[]) => React.ReactNode;
39
45
  /** Separator for displaying selected path */
40
46
  separator?: React.ReactNode;
41
47
  /** Show error state */
@@ -53,6 +59,6 @@ interface CascaderExtendedProps<V extends CascaderOptionValue, O extends Cascade
53
59
  /** Width of the menu */
54
60
  menuWidth?: number | 'exact-reference' | 'min-reference';
55
61
  }
56
- export type CascaderProps<V extends CascaderOptionValue = CascaderOptionValue, O extends CascaderOption<V> = CascaderOption<V>> = ShallowMerge<InputMaskProps<JSX.IntrinsicElements['button']>, CascaderExtendedProps<V, O>>;
62
+ export type CascaderProps = ShallowMerge<InputMaskProps<JSX.IntrinsicElements['button']>, CascaderExtendedProps>;
57
63
  export {};
58
64
  //# sourceMappingURL=types.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/lib/cascader/types.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/lib/cascader/types.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,GAAG,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAEvD,OAAO,EAAE,SAAS,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAC;AACnE,OAAO,EAAE,gBAAgB,EAAE,MAAM,6BAA6B,CAAC;AAE/D,OAAO,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AACtC,OAAO,EAAE,cAAc,EAAE,wBAAwB,EAAE,MAAM,qBAAqB,CAAC;AAC/E,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACvC,OAAO,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAE9C,MAAM,MAAM,uBAAuB,GAAG,wBAAwB,CAAC;AAE/D,MAAM,MAAM,mBAAmB,GAAG,MAAM,GAAG,MAAM,CAAC;AAElD,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IAC/B,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,KAAK,CAAC,SAAS,CAAC;IACvB,eAAe,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAClC,WAAW,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC;IAChC,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,QAAQ,CAAC,EAAE,cAAc,EAAE,CAAC;IAC5B,qIAAqI;IACrI,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB;AAED,UAAU,qBAAsB,SAAQ,gBAAgB,CAAC,uBAAuB,CAAC;IAC/E,gCAAgC;IAChC,SAAS,CAAC,EAAE,SAAS,CAAC;IACtB,gDAAgD;IAChD,YAAY,CAAC,EAAE,kBAAkB,CAAC,cAAc,CAAC,CAAC;IAClD,4BAA4B;IAC5B,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,mCAAmC;IACnC,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,gEAAgE;IAChE,+BAA+B;IAC/B,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC;IACjB,aAAa,CAAC,EAAE,SAAS,CAAC;IAC1B,wBAAwB;IACxB,OAAO,EAAE,cAAc,EAAE,CAAC;IAC1B,yIAAyI;IACzI,WAAW,CAAC,EAAE,CAAC,IAAI,EAAE,cAAc,EAAE,KAAK,OAAO,CAAC,cAAc,EAAE,CAAC,CAAC;IACpE,sCAAsC;IACtC,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,EAAE,eAAe,EAAE,cAAc,EAAE,KAAK,IAAI,CAAC;IACxE,uBAAuB;IACvB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,2CAA2C;IAC3C,SAAS,CAAC,EAAE,cAAc,CAAC,cAAc,CAAC,CAAC;IAC3C,iDAAiD;IACjD,6CAA6C;IAC7C,SAAS,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAC5B,uBAAuB;IACvB,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,kCAAkC;IAClC,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,kCAAkC;IAClC,cAAc,CAAC,EAAE,cAAc,CAAC,GAAG,CAAC,iBAAiB,CAAC,KAAK,CAAC,CAAC,CAAC;IAC9D,iCAAiC;IACjC,UAAU,CAAC,EAAE,UAAU,CAAC;IACxB,yCAAyC;IACzC,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,8BAA8B;IAC9B,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,wBAAwB;IACxB,SAAS,CAAC,EAAE,MAAM,GAAG,iBAAiB,GAAG,eAAe,CAAC;CAC1D;AAED,MAAM,MAAM,aAAa,GAAG,YAAY,CAAC,cAAc,CAAC,GAAG,CAAC,iBAAiB,CAAC,QAAQ,CAAC,CAAC,EAAE,qBAAqB,CAAC,CAAC"}
@@ -1,5 +1,6 @@
1
1
  import { CSSObject } from '@emotion/serialize';
2
2
  import { Screen } from '../theme';
3
+ import type * as CSS from "csstype";
3
4
  export type Nullable<T> = T | null;
4
5
  export type Dict<T> = Record<string, T>;
5
6
  export type ShallowMerge<T1, T2> = Omit<T1, keyof T2> & T2;
@@ -11,7 +12,17 @@ export type ProgressDirection = "horizontal" | "vertical";
11
12
  export type ContentTranslation = {
12
13
  key: string;
13
14
  };
15
+ /**
16
+ * Stricter version of Emotion's CSSObject.
17
+ *
18
+ * Overrides all standard CSS properties with `CSS.Properties` from csstype
19
+ * so values only accept `string | number`, never an array.
20
+ * Pseudos and nested selectors also recurse through StrictCSSObject.
21
+ */
22
+ export type StyledCSS = Omit<CSSObject, keyof CSS.Properties | keyof CSS.Pseudos> & CSS.Properties<number | string> & {
23
+ [K in CSS.Pseudos]?: StyledCSS;
24
+ };
14
25
  export type PropsWithCSS<T extends object = object> = T & {
15
- css?: CSSObject;
26
+ css?: StyledCSS;
16
27
  };
17
28
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/types/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAC/C,OAAO,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AAElC,MAAM,MAAM,QAAQ,CAAC,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;AAEnC,MAAM,MAAM,IAAI,CAAC,CAAC,IAAI,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;AAExC,MAAM,MAAM,YAAY,CAAC,EAAE,EAAE,EAAE,IAAI,IAAI,CAAC,EAAE,EAAE,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC;AAE3D,MAAM,MAAM,gBAAgB,CAAC,CAAC,GAAG,OAAO,IAAI,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,CAAC;AAEvE,MAAM,MAAM,WAAW,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,CAAC;AAEpD,MAAM,MAAM,YAAY,GACpB,SAAS,GACT,WAAW,GACX,OAAO,GACP,KAAK,GACL,QAAQ,GACR,MAAM,GACN,SAAS,CAAC;AAEd,MAAM,MAAM,aAAa,GAAG,WAAW,GAAG,UAAU,GAAG,MAAM,CAAC;AAE9D,MAAM,MAAM,iBAAiB,GAAG,YAAY,GAAG,UAAU,CAAC;AAE1D,MAAM,MAAM,kBAAkB,GAAG;IAC/B,GAAG,EAAE,MAAM,CAAC;CACb,CAAC;AAEF,MAAM,MAAM,YAAY,CAAC,CAAC,SAAS,MAAM,GAAG,MAAM,IAAI,CAAC,GAAG;IACxD,GAAG,CAAC,EAAE,SAAS,CAAC;CACjB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/types/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAC/C,OAAO,KAAK,KAAK,GAAG,MAAM,SAAS,CAAC;AACpC,OAAO,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AAElC,MAAM,MAAM,QAAQ,CAAC,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;AAEnC,MAAM,MAAM,IAAI,CAAC,CAAC,IAAI,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;AAExC,MAAM,MAAM,YAAY,CAAC,EAAE,EAAE,EAAE,IAAI,IAAI,CAAC,EAAE,EAAE,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC;AAE3D,MAAM,MAAM,gBAAgB,CAAC,CAAC,GAAG,OAAO,IAAI,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,CAAC;AAEvE,MAAM,MAAM,WAAW,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,CAAC;AAEpD,MAAM,MAAM,YAAY,GACpB,SAAS,GACT,WAAW,GACX,OAAO,GACP,KAAK,GACL,QAAQ,GACR,MAAM,GACN,SAAS,CAAC;AAEd,MAAM,MAAM,aAAa,GAAG,WAAW,GAAG,UAAU,GAAG,MAAM,CAAC;AAE9D,MAAM,MAAM,iBAAiB,GAAG,YAAY,GAAG,UAAU,CAAC;AAE1D,MAAM,MAAM,kBAAkB,GAAG;IAC/B,GAAG,EAAE,MAAM,CAAC;CACb,CAAC;AAEF;;;;;;GAMG;AAEH,MAAM,MAAM,SAAS,GAAG,IAAI,CAC1B,SAAS,EACT,MAAM,GAAG,CAAC,UAAU,GAAG,MAAM,GAAG,CAAC,OAAO,CACzC,GACC,GAAG,CAAC,UAAU,CAAC,MAAM,GAAG,MAAM,CAAC,GAAG;KAAG,CAAC,IAAI,GAAG,CAAC,OAAO,CAAC,CAAC,EAAE,SAAS;CAAE,CAAC;AAEvE,MAAM,MAAM,YAAY,CAAC,CAAC,SAAS,MAAM,GAAG,MAAM,IAAI,CAAC,GAAG;IACxD,GAAG,CAAC,EAAE,SAAS,CAAC;CACjB,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@janbox/storefront-ui",
3
- "version": "1.0.3",
3
+ "version": "1.0.5",
4
4
  "description": "Storefront UI component library for Janbox",
5
5
  "author": "Janbox",
6
6
  "keywords": [
@@ -91,7 +91,6 @@
91
91
  "react-i18next": "^14.0.0",
92
92
  "react-player": "^3.3.3",
93
93
  "react-router": "^7.9.6",
94
- "react-use": "^17.5.1",
95
94
  "react-zoom-pan-pinch": "^3.7.0",
96
95
  "slugify": "^1.6.6",
97
96
  "type-fest": "^5.2.0",
@@ -1,5 +0,0 @@
1
- import isDeepEqualReact from "/Users/akashi/Work/iChiba/@janbox/storefront-ui/node_modules/.pnpm/fast-deep-equal@3.1.3/node_modules/fast-deep-equal/react.js";
2
- import { default as default2 } from "/Users/akashi/Work/iChiba/@janbox/storefront-ui/node_modules/.pnpm/fast-deep-equal@3.1.3/node_modules/fast-deep-equal/react.js";
3
- export {
4
- default2 as default
5
- };