@timmbr/ui 1.9.0 → 1.11.0
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/components/Breadcrumb/Breadcrumb.d.ts +9 -0
- package/dist/components/Breadcrumb/Breadcrumb.d.ts.map +1 -0
- package/dist/components/Breadcrumb/Breadcrumb.js +32 -0
- package/dist/components/Breadcrumb/Breadcrumb.styles.d.ts +8 -0
- package/dist/components/Breadcrumb/Breadcrumb.styles.d.ts.map +1 -0
- package/dist/components/Breadcrumb/Breadcrumb.styles.js +20 -0
- package/dist/components/Breadcrumb/Breadcrumb.types.d.ts +27 -0
- package/dist/components/Breadcrumb/Breadcrumb.types.d.ts.map +1 -0
- package/dist/components/Breadcrumb/index.d.ts +4 -0
- package/dist/components/Breadcrumb/index.d.ts.map +1 -0
- package/dist/components/Chip/Chip.d.ts.map +1 -1
- package/dist/components/Chip/Chip.js +13 -3
- package/dist/components/Chip/Chip.types.d.ts +5 -0
- package/dist/components/Chip/Chip.types.d.ts.map +1 -1
- package/dist/components/Drawer/Drawer.d.ts.map +1 -1
- package/dist/components/Drawer/Drawer.js +4 -4
- package/dist/components/Drawer/Drawer.styles.d.ts +1 -0
- package/dist/components/Drawer/Drawer.styles.d.ts.map +1 -1
- package/dist/components/Drawer/Drawer.styles.js +7 -1
- package/dist/components/Drawer/Drawer.types.d.ts +2 -0
- package/dist/components/Drawer/Drawer.types.d.ts.map +1 -1
- package/dist/components/FilterChips/FilterChips.d.ts +8 -0
- package/dist/components/FilterChips/FilterChips.d.ts.map +1 -0
- package/dist/components/FilterChips/FilterChips.js +39 -0
- package/dist/components/FilterChips/FilterChips.types.d.ts +17 -0
- package/dist/components/FilterChips/FilterChips.types.d.ts.map +1 -0
- package/dist/components/FilterChips/index.d.ts +3 -0
- package/dist/components/FilterChips/index.d.ts.map +1 -0
- package/dist/components/FilterDrawer/FilterDrawer.d.ts +12 -0
- package/dist/components/FilterDrawer/FilterDrawer.d.ts.map +1 -0
- package/dist/components/FilterDrawer/FilterDrawer.js +157 -0
- package/dist/components/FilterDrawer/FilterDrawer.styles.d.ts +12 -0
- package/dist/components/FilterDrawer/FilterDrawer.styles.d.ts.map +1 -0
- package/dist/components/FilterDrawer/FilterDrawer.styles.js +30 -0
- package/dist/components/FilterDrawer/FilterDrawer.types.d.ts +28 -0
- package/dist/components/FilterDrawer/FilterDrawer.types.d.ts.map +1 -0
- package/dist/components/FilterDrawer/index.d.ts +4 -0
- package/dist/components/FilterDrawer/index.d.ts.map +1 -0
- package/dist/components/FilterPanel/FilterPanel.d.ts +33 -0
- package/dist/components/FilterPanel/FilterPanel.d.ts.map +1 -0
- package/dist/components/FilterPanel/FilterPanel.js +239 -0
- package/dist/components/FilterPanel/FilterPanel.styles.d.ts +16 -0
- package/dist/components/FilterPanel/FilterPanel.styles.d.ts.map +1 -0
- package/dist/components/FilterPanel/FilterPanel.styles.js +31 -0
- package/dist/components/FilterPanel/FilterPanel.types.d.ts +80 -0
- package/dist/components/FilterPanel/FilterPanel.types.d.ts.map +1 -0
- package/dist/components/FilterPanel/FilterPanel.types.js +3 -0
- package/dist/components/FilterPanel/index.d.ts +4 -0
- package/dist/components/FilterPanel/index.d.ts.map +1 -0
- package/dist/components/ImageUpload/ImageUpload.styles.d.ts +3 -3
- package/dist/components/MediaCard/MediaCard.d.ts.map +1 -1
- package/dist/components/MediaCard/MediaCard.js +3 -1
- package/dist/components/NavHeader/NavHeader.styles.d.ts +7 -0
- package/dist/components/NavHeader/NavHeader.styles.d.ts.map +1 -1
- package/dist/components/NavHeader/NavHeader.styles.js +20 -2
- package/dist/components/NavHeader/NavHeader.types.d.ts +59 -9
- package/dist/components/NavHeader/NavHeader.types.d.ts.map +1 -1
- package/dist/components/NavHeader/index.d.ts +3 -2
- package/dist/components/NavHeader/index.d.ts.map +1 -1
- package/dist/components/NavHeader/subcomponents/NavActions.d.ts +4 -4
- package/dist/components/NavHeader/subcomponents/NavActions.d.ts.map +1 -1
- package/dist/components/NavHeader/subcomponents/NavActions.js +31 -25
- package/dist/components/NavHeader/subcomponents/NavMobileSearchDrawer.d.ts.map +1 -1
- package/dist/components/NavHeader/subcomponents/NavMobileSearchDrawer.js +15 -33
- package/dist/components/NavHeader/subcomponents/NavSearch.d.ts.map +1 -1
- package/dist/components/NavHeader/subcomponents/NavSearch.js +37 -83
- package/dist/components/NavHeader/subcomponents/NavSearchPanel.d.ts +63 -0
- package/dist/components/NavHeader/subcomponents/NavSearchPanel.d.ts.map +1 -0
- package/dist/components/NavHeader/subcomponents/NavSearchPanel.js +289 -0
- package/dist/components/NavMenuColumns/NavMenuColumns.styles.js +1 -1
- package/dist/components/OptionPicker/OptionPicker.d.ts +10 -0
- package/dist/components/OptionPicker/OptionPicker.d.ts.map +1 -0
- package/dist/components/OptionPicker/OptionPicker.js +116 -0
- package/dist/components/OptionPicker/OptionPicker.styles.d.ts +20 -0
- package/dist/components/OptionPicker/OptionPicker.styles.d.ts.map +1 -0
- package/dist/components/OptionPicker/OptionPicker.styles.js +60 -0
- package/dist/components/OptionPicker/OptionPicker.types.d.ts +39 -0
- package/dist/components/OptionPicker/OptionPicker.types.d.ts.map +1 -0
- package/dist/components/OptionPicker/index.d.ts +4 -0
- package/dist/components/OptionPicker/index.d.ts.map +1 -0
- package/dist/components/Price/Price.styles.d.ts.map +1 -1
- package/dist/components/Price/Price.styles.js +3 -2
- package/dist/components/ProductGallery/ProductGallery.d.ts +10 -0
- package/dist/components/ProductGallery/ProductGallery.d.ts.map +1 -0
- package/dist/components/ProductGallery/ProductGallery.js +306 -0
- package/dist/components/ProductGallery/ProductGallery.styles.d.ts +32 -0
- package/dist/components/ProductGallery/ProductGallery.styles.d.ts.map +1 -0
- package/dist/components/ProductGallery/ProductGallery.styles.js +86 -0
- package/dist/components/ProductGallery/ProductGallery.types.d.ts +55 -0
- package/dist/components/ProductGallery/ProductGallery.types.d.ts.map +1 -0
- package/dist/components/ProductGallery/ProductGalleryLightbox.d.ts +20 -0
- package/dist/components/ProductGallery/ProductGalleryLightbox.d.ts.map +1 -0
- package/dist/components/ProductGallery/ProductGalleryLightbox.js +210 -0
- package/dist/components/ProductGallery/index.d.ts +4 -0
- package/dist/components/ProductGallery/index.d.ts.map +1 -0
- package/dist/components/QuantityStepper/QuantityStepper.d.ts +8 -0
- package/dist/components/QuantityStepper/QuantityStepper.d.ts.map +1 -0
- package/dist/components/QuantityStepper/QuantityStepper.js +65 -0
- package/dist/components/QuantityStepper/QuantityStepper.styles.d.ts +8 -0
- package/dist/components/QuantityStepper/QuantityStepper.styles.d.ts.map +1 -0
- package/dist/components/QuantityStepper/QuantityStepper.styles.js +24 -0
- package/dist/components/QuantityStepper/QuantityStepper.types.d.ts +20 -0
- package/dist/components/QuantityStepper/QuantityStepper.types.d.ts.map +1 -0
- package/dist/components/QuantityStepper/index.d.ts +4 -0
- package/dist/components/QuantityStepper/index.d.ts.map +1 -0
- package/dist/components/RadioCard/RadioCard.d.ts +9 -0
- package/dist/components/RadioCard/RadioCard.d.ts.map +1 -0
- package/dist/components/RadioCard/RadioCard.js +40 -0
- package/dist/components/RadioCard/RadioCard.styles.d.ts +9 -0
- package/dist/components/RadioCard/RadioCard.styles.d.ts.map +1 -0
- package/dist/components/RadioCard/RadioCard.styles.js +24 -0
- package/dist/components/RadioCard/RadioCard.types.d.ts +28 -0
- package/dist/components/RadioCard/RadioCard.types.d.ts.map +1 -0
- package/dist/components/RadioCard/index.d.ts +4 -0
- package/dist/components/RadioCard/index.d.ts.map +1 -0
- package/dist/components/RangeSlider/RangeSlider.d.ts.map +1 -1
- package/dist/components/RangeSlider/RangeSlider.js +5 -3
- package/dist/components/RangeSlider/RangeSlider.types.d.ts +7 -0
- package/dist/components/RangeSlider/RangeSlider.types.d.ts.map +1 -1
- package/dist/components/Select/Select.d.ts.map +1 -1
- package/dist/components/Select/Select.js +14 -1
- package/dist/components/Select/Select.types.d.ts +4 -0
- package/dist/components/Select/Select.types.d.ts.map +1 -1
- package/dist/components/Skeleton/Skeleton.styles.d.ts +1 -1
- package/dist/components/Snackbar/Snackbar.d.ts +9 -0
- package/dist/components/Snackbar/Snackbar.d.ts.map +1 -0
- package/dist/components/Snackbar/Snackbar.js +108 -0
- package/dist/components/Snackbar/Snackbar.styles.d.ts +17 -0
- package/dist/components/Snackbar/Snackbar.styles.d.ts.map +1 -0
- package/dist/components/Snackbar/Snackbar.styles.js +37 -0
- package/dist/components/Snackbar/Snackbar.types.d.ts +36 -0
- package/dist/components/Snackbar/Snackbar.types.d.ts.map +1 -0
- package/dist/components/Snackbar/SnackbarHost.d.ts +4 -0
- package/dist/components/Snackbar/SnackbarHost.d.ts.map +1 -0
- package/dist/components/Snackbar/SnackbarHost.js +24 -0
- package/dist/components/Snackbar/index.d.ts +6 -0
- package/dist/components/Snackbar/index.d.ts.map +1 -0
- package/dist/components/Snackbar/snackbarStore.d.ts +42 -0
- package/dist/components/Snackbar/snackbarStore.d.ts.map +1 -0
- package/dist/components/Snackbar/snackbarStore.js +87 -0
- package/dist/components/StockMeter/StockMeter.d.ts +8 -0
- package/dist/components/StockMeter/StockMeter.d.ts.map +1 -0
- package/dist/components/StockMeter/StockMeter.js +19 -0
- package/dist/components/StockMeter/StockMeter.styles.d.ts +4 -0
- package/dist/components/StockMeter/StockMeter.styles.d.ts.map +1 -0
- package/dist/components/StockMeter/StockMeter.styles.js +7 -0
- package/dist/components/StockMeter/StockMeter.types.d.ts +10 -0
- package/dist/components/StockMeter/StockMeter.types.d.ts.map +1 -0
- package/dist/components/StockMeter/index.d.ts +4 -0
- package/dist/components/StockMeter/index.d.ts.map +1 -0
- package/dist/components/Swatch/Swatch.d.ts +11 -0
- package/dist/components/Swatch/Swatch.d.ts.map +1 -0
- package/dist/components/Swatch/Swatch.js +40 -0
- package/dist/components/Swatch/Swatch.styles.d.ts +8 -0
- package/dist/components/Swatch/Swatch.styles.d.ts.map +1 -0
- package/dist/components/Swatch/Swatch.styles.js +26 -0
- package/dist/components/Swatch/Swatch.types.d.ts +11 -0
- package/dist/components/Swatch/Swatch.types.d.ts.map +1 -0
- package/dist/components/Swatch/index.d.ts +4 -0
- package/dist/components/Swatch/index.d.ts.map +1 -0
- package/dist/components/Toast/Toast.d.ts.map +1 -1
- package/dist/components/Toast/Toast.js +49 -42
- package/dist/components/Toast/Toast.types.d.ts +7 -0
- package/dist/components/Toast/Toast.types.d.ts.map +1 -1
- package/dist/components/Toast/ToastContainer.d.ts.map +1 -1
- package/dist/components/Toast/ToastContainer.js +5 -0
- package/dist/components/Toast/toastStore.d.ts +11 -0
- package/dist/components/Toast/toastStore.d.ts.map +1 -1
- package/dist/components/Toast/toastStore.js +70 -30
- package/dist/index.d.ts +11 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +26 -1
- package/dist/providers/TimmbrConfigProvider.d.ts.map +1 -1
- package/dist/providers/TimmbrConfigProvider.js +5 -9
- package/package.json +5 -5
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import type { BreadcrumbProps } from './Breadcrumb.types';
|
|
3
|
+
/**
|
|
4
|
+
* Where the current page sits (Home › Living › Sofas). The last item is the current page
|
|
5
|
+
* (`aria-current="page"`, not a link). On small screens a long trail keeps its first and last
|
|
6
|
+
* two items and collapses the middle behind "…". Server-safe: no client JavaScript.
|
|
7
|
+
*/
|
|
8
|
+
export declare const Breadcrumb: React.ForwardRefExoticComponent<BreadcrumbProps & React.RefAttributes<HTMLElement>>;
|
|
9
|
+
//# sourceMappingURL=Breadcrumb.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Breadcrumb.d.ts","sourceRoot":"","sources":["../../../src/components/Breadcrumb/Breadcrumb.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAU/B,OAAO,KAAK,EAAuB,eAAe,EAAE,MAAM,oBAAoB,CAAC;AAQ/E;;;;GAIG;AACH,eAAO,MAAM,UAAU,qFA6CtB,CAAC"}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { jsx, jsxs } from 'react/jsx-runtime';
|
|
2
|
+
import * as React from 'react';
|
|
3
|
+
import { ChevronRight } from '@timmbr/icons';
|
|
4
|
+
import { cn } from '@timmbr/utils';
|
|
5
|
+
import { breadcrumbSeparatorVariants, breadcrumbCurrentVariants, breadcrumbLinkVariants, breadcrumbItemVariants, breadcrumbListVariants } from './Breadcrumb.styles.js';
|
|
6
|
+
|
|
7
|
+
const PlainLink = ({ href, className, children }) => /* @__PURE__ */ jsx("a", { href, className, children });
|
|
8
|
+
const Breadcrumb = React.forwardRef(
|
|
9
|
+
({ items, linkComponent: Link = PlainLink, ariaLabel = "Breadcrumb", collapseAfter = 3, className, ...props }, ref) => {
|
|
10
|
+
if (items.length === 0) return null;
|
|
11
|
+
const collapse = items.length > Math.max(collapseAfter, 3);
|
|
12
|
+
const lastIndex = items.length - 1;
|
|
13
|
+
return /* @__PURE__ */ jsx("nav", { ref, "aria-label": ariaLabel, "data-slot": "breadcrumb", className, ...props, children: /* @__PURE__ */ jsx("ol", { className: breadcrumbListVariants(), children: items.map((item, index) => {
|
|
14
|
+
const isLast = index === lastIndex;
|
|
15
|
+
const hidden = collapse && index > 0 && index < lastIndex - 1;
|
|
16
|
+
const ItemLink = item.crossZone ? PlainLink : Link;
|
|
17
|
+
return /* @__PURE__ */ jsxs(React.Fragment, { children: [
|
|
18
|
+
collapse && index === 1 && /* @__PURE__ */ jsxs("li", { "aria-hidden": "true", className: "inline-flex items-center gap-1.5 sm:hidden", children: [
|
|
19
|
+
/* @__PURE__ */ jsx("span", { children: "…" }),
|
|
20
|
+
/* @__PURE__ */ jsx(ChevronRight, { className: breadcrumbSeparatorVariants() })
|
|
21
|
+
] }),
|
|
22
|
+
/* @__PURE__ */ jsxs("li", { className: cn(breadcrumbItemVariants({ collapsible: hidden })), children: [
|
|
23
|
+
isLast || !item.href ? /* @__PURE__ */ jsx("span", { className: breadcrumbCurrentVariants(), ...isLast && { "aria-current": "page" }, children: item.label }) : /* @__PURE__ */ jsx(ItemLink, { href: item.href, className: breadcrumbLinkVariants(), children: item.label }),
|
|
24
|
+
!isLast && /* @__PURE__ */ jsx(ChevronRight, { "aria-hidden": "true", className: breadcrumbSeparatorVariants() })
|
|
25
|
+
] })
|
|
26
|
+
] }, index);
|
|
27
|
+
}) }) });
|
|
28
|
+
}
|
|
29
|
+
);
|
|
30
|
+
Breadcrumb.displayName = "Breadcrumb";
|
|
31
|
+
|
|
32
|
+
export { Breadcrumb };
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export declare const breadcrumbListVariants: (props?: import("class-variance-authority/types").ClassProp | undefined) => string;
|
|
2
|
+
export declare const breadcrumbItemVariants: (props?: ({
|
|
3
|
+
collapsible?: boolean | null | undefined;
|
|
4
|
+
} & import("class-variance-authority/types").ClassProp) | undefined) => string;
|
|
5
|
+
export declare const breadcrumbLinkVariants: (props?: import("class-variance-authority/types").ClassProp | undefined) => string;
|
|
6
|
+
export declare const breadcrumbCurrentVariants: (props?: import("class-variance-authority/types").ClassProp | undefined) => string;
|
|
7
|
+
export declare const breadcrumbSeparatorVariants: (props?: import("class-variance-authority/types").ClassProp | undefined) => string;
|
|
8
|
+
//# sourceMappingURL=Breadcrumb.styles.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Breadcrumb.styles.d.ts","sourceRoot":"","sources":["../../../src/components/Breadcrumb/Breadcrumb.styles.ts"],"names":[],"mappings":"AAEA,eAAO,MAAM,sBAAsB,oFAAiF,CAAC;AAErH,eAAO,MAAM,sBAAsB;;8EASjC,CAAC;AAEH,eAAO,MAAM,sBAAsB,oFAElC,CAAC;AAEF,eAAO,MAAM,yBAAyB,oFAA4C,CAAC;AAEnF,eAAO,MAAM,2BAA2B,oFAAyC,CAAC"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { cva } from 'class-variance-authority';
|
|
2
|
+
|
|
3
|
+
const breadcrumbListVariants = cva("flex flex-wrap items-center gap-1.5 font-sans text-body-3 text-grey-600");
|
|
4
|
+
const breadcrumbItemVariants = cva("inline-flex min-w-0 items-center gap-1.5", {
|
|
5
|
+
variants: {
|
|
6
|
+
/** Middle items hidden on small screens when the trail is long. */
|
|
7
|
+
collapsible: {
|
|
8
|
+
true: "hidden sm:inline-flex",
|
|
9
|
+
false: ""
|
|
10
|
+
}
|
|
11
|
+
},
|
|
12
|
+
defaultVariants: { collapsible: false }
|
|
13
|
+
});
|
|
14
|
+
const breadcrumbLinkVariants = cva(
|
|
15
|
+
"truncate rounded-sm transition-colors hover:text-primary focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring"
|
|
16
|
+
);
|
|
17
|
+
const breadcrumbCurrentVariants = cva("truncate font-medium text-grey-950");
|
|
18
|
+
const breadcrumbSeparatorVariants = cva("size-3.5 shrink-0 text-grey-400");
|
|
19
|
+
|
|
20
|
+
export { breadcrumbCurrentVariants, breadcrumbItemVariants, breadcrumbLinkVariants, breadcrumbListVariants, breadcrumbSeparatorVariants };
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import type * as React from 'react';
|
|
2
|
+
export interface BreadcrumbItem {
|
|
3
|
+
label: React.ReactNode;
|
|
4
|
+
/** Omit for the current page (the last item). */
|
|
5
|
+
href?: string;
|
|
6
|
+
/** Link into another zone (e.g. Home in the shell): a plain anchor, not `linkComponent`. */
|
|
7
|
+
crossZone?: boolean;
|
|
8
|
+
}
|
|
9
|
+
export interface BreadcrumbLinkProps {
|
|
10
|
+
href: string;
|
|
11
|
+
className?: string;
|
|
12
|
+
children: React.ReactNode;
|
|
13
|
+
}
|
|
14
|
+
export interface BreadcrumbProps extends Omit<React.HTMLAttributes<HTMLElement>, 'children'> {
|
|
15
|
+
/** Root first; the last item is the current page. */
|
|
16
|
+
items: BreadcrumbItem[];
|
|
17
|
+
/** Client-side link (e.g. Next.js Link). Defaults to a plain anchor. */
|
|
18
|
+
linkComponent?: React.ComponentType<BreadcrumbLinkProps>;
|
|
19
|
+
/** Accessible name of the navigation landmark. */
|
|
20
|
+
ariaLabel?: string;
|
|
21
|
+
/**
|
|
22
|
+
* On small screens, collapse the middle items behind "…" when there are more than this many.
|
|
23
|
+
* @default 3
|
|
24
|
+
*/
|
|
25
|
+
collapseAfter?: number;
|
|
26
|
+
}
|
|
27
|
+
//# sourceMappingURL=Breadcrumb.types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Breadcrumb.types.d.ts","sourceRoot":"","sources":["../../../src/components/Breadcrumb/Breadcrumb.types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,KAAK,MAAM,OAAO,CAAC;AAEpC,MAAM,WAAW,cAAc;IAC7B,KAAK,EAAE,KAAK,CAAC,SAAS,CAAC;IACvB,iDAAiD;IACjD,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,4FAA4F;IAC5F,SAAS,CAAC,EAAE,OAAO,CAAC;CACrB;AAED,MAAM,WAAW,mBAAmB;IAClC,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;CAC3B;AAED,MAAM,WAAW,eAAgB,SAAQ,IAAI,CAAC,KAAK,CAAC,cAAc,CAAC,WAAW,CAAC,EAAE,UAAU,CAAC;IAC1F,qDAAqD;IACrD,KAAK,EAAE,cAAc,EAAE,CAAC;IACxB,wEAAwE;IACxE,aAAa,CAAC,EAAE,KAAK,CAAC,aAAa,CAAC,mBAAmB,CAAC,CAAC;IACzD,kDAAkD;IAClD,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB;;;OAGG;IACH,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/components/Breadcrumb/index.ts"],"names":[],"mappings":"AAAA,cAAc,cAAc,CAAC;AAC7B,cAAc,oBAAoB,CAAC;AACnC,cAAc,qBAAqB,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Chip.d.ts","sourceRoot":"","sources":["../../../src/components/Chip/Chip.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAM/B,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAE9C,eAAO,MAAM,IAAI,
|
|
1
|
+
{"version":3,"file":"Chip.d.ts","sourceRoot":"","sources":["../../../src/components/Chip/Chip.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAM/B,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAE9C,eAAO,MAAM,IAAI,kFAmFhB,CAAC"}
|
|
@@ -17,9 +17,11 @@ const Chip = React.forwardRef(
|
|
|
17
17
|
clickable,
|
|
18
18
|
icon,
|
|
19
19
|
onRemove,
|
|
20
|
+
removeLabel = "Remove",
|
|
20
21
|
motion,
|
|
21
22
|
onClick,
|
|
22
23
|
children,
|
|
24
|
+
onKeyDown,
|
|
23
25
|
...props
|
|
24
26
|
}, ref) => {
|
|
25
27
|
const isInteractive = clickable || !!onClick;
|
|
@@ -37,6 +39,14 @@ const Chip = React.forwardRef(
|
|
|
37
39
|
role: isInteractive ? "button" : void 0,
|
|
38
40
|
tabIndex: isInteractive ? 0 : void 0,
|
|
39
41
|
onClick,
|
|
42
|
+
onKeyDown: (e) => {
|
|
43
|
+
onKeyDown?.(e);
|
|
44
|
+
if (e.defaultPrevented || !isInteractive || !onRemove) return;
|
|
45
|
+
if (e.key === "Delete" || e.key === "Backspace") {
|
|
46
|
+
e.preventDefault();
|
|
47
|
+
onRemove(e);
|
|
48
|
+
}
|
|
49
|
+
},
|
|
40
50
|
className: cn(
|
|
41
51
|
chipVariants({
|
|
42
52
|
variant: selected ? "filled" : variant,
|
|
@@ -57,10 +67,10 @@ const Chip = React.forwardRef(
|
|
|
57
67
|
"button",
|
|
58
68
|
{
|
|
59
69
|
type: "button",
|
|
60
|
-
tabIndex: -1,
|
|
70
|
+
tabIndex: isInteractive ? -1 : void 0,
|
|
61
71
|
onClick: handleRemove,
|
|
62
|
-
"aria-label":
|
|
63
|
-
className: "shrink-0 -mr-1 size-4 rounded-full inline-flex items-center justify-center opacity-70 hover:opacity-100 hover:bg-grey-1000/10 dark:hover:bg-grey-50/20 transition-all cursor-pointer",
|
|
72
|
+
"aria-label": removeLabel,
|
|
73
|
+
className: "shrink-0 -mr-1 size-4 rounded-full inline-flex items-center justify-center opacity-70 hover:opacity-100 hover:bg-grey-1000/10 dark:hover:bg-grey-50/20 transition-all cursor-pointer focus-visible:opacity-100 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring",
|
|
64
74
|
children: /* @__PURE__ */ jsx(X, { className: "size-3" })
|
|
65
75
|
}
|
|
66
76
|
)
|
|
@@ -18,6 +18,11 @@ export interface ChipProps extends Omit<React.HTMLAttributes<HTMLDivElement>, 'c
|
|
|
18
18
|
* Callback fired when the remove button is clicked. If provided, renders an X button.
|
|
19
19
|
*/
|
|
20
20
|
onRemove?: (e: React.MouseEvent) => void;
|
|
21
|
+
/**
|
|
22
|
+
* Accessible name of the remove button, e.g. "Remove Teak".
|
|
23
|
+
* @default 'Remove'
|
|
24
|
+
*/
|
|
25
|
+
removeLabel?: string;
|
|
21
26
|
/**
|
|
22
27
|
* Motion transition control.
|
|
23
28
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Chip.types.d.ts","sourceRoot":"","sources":["../../../src/components/Chip/Chip.types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,KAAK,MAAM,OAAO,CAAC;AACpC,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAClD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAErD,MAAM,WAAW,SACf,SAAQ,IAAI,CAAC,KAAK,CAAC,cAAc,CAAC,cAAc,CAAC,EAAE,OAAO,CAAC,EACzD,YAAY;IACd;;OAEG;IACH,IAAI,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IACvB;;OAEG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB;;OAEG;IACH,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB;;OAEG;IACH,QAAQ,CAAC,EAAE,CAAC,CAAC,EAAE,KAAK,CAAC,UAAU,KAAK,IAAI,CAAC;IACzC;;OAEG;IACH,MAAM,CAAC,EAAE,UAAU,CAAC;CACrB"}
|
|
1
|
+
{"version":3,"file":"Chip.types.d.ts","sourceRoot":"","sources":["../../../src/components/Chip/Chip.types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,KAAK,MAAM,OAAO,CAAC;AACpC,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAClD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAErD,MAAM,WAAW,SACf,SAAQ,IAAI,CAAC,KAAK,CAAC,cAAc,CAAC,cAAc,CAAC,EAAE,OAAO,CAAC,EACzD,YAAY;IACd;;OAEG;IACH,IAAI,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IACvB;;OAEG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB;;OAEG;IACH,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB;;OAEG;IACH,QAAQ,CAAC,EAAE,CAAC,CAAC,EAAE,KAAK,CAAC,UAAU,KAAK,IAAI,CAAC;IACzC;;;OAGG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB;;OAEG;IACH,MAAM,CAAC,EAAE,UAAU,CAAC;CACrB"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Drawer.d.ts","sourceRoot":"","sources":["../../../src/components/Drawer/Drawer.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAC/B,OAAO,KAAK,eAAe,MAAM,wBAAwB,CAAC;AAc1D,OAAO,KAAK,EACV,WAAW,EACX,kBAAkB,EAClB,iBAAiB,EACjB,iBAAiB,EACjB,eAAe,EAChB,MAAM,gBAAgB,CAAC;AAExB,eAAO,MAAM,MAAM,EAAE,KAAK,CAAC,EAAE,CAAC,WAAW,CAAwB,CAAC;AAClE,eAAO,MAAM,aAAa,8GAA0B,CAAC;AACrD,eAAO,MAAM,YAAY,6CAAyB,CAAC;AACnD,eAAO,MAAM,WAAW,4GAAwB,CAAC;AAEjD,eAAO,MAAM,aAAa,8JAUxB,CAAC;AAGH,eAAO,MAAM,aAAa,
|
|
1
|
+
{"version":3,"file":"Drawer.d.ts","sourceRoot":"","sources":["../../../src/components/Drawer/Drawer.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAC/B,OAAO,KAAK,eAAe,MAAM,wBAAwB,CAAC;AAc1D,OAAO,KAAK,EACV,WAAW,EACX,kBAAkB,EAClB,iBAAiB,EACjB,iBAAiB,EACjB,eAAe,EAChB,MAAM,gBAAgB,CAAC;AAExB,eAAO,MAAM,MAAM,EAAE,KAAK,CAAC,EAAE,CAAC,WAAW,CAAwB,CAAC;AAClE,eAAO,MAAM,aAAa,8GAA0B,CAAC;AACrD,eAAO,MAAM,YAAY,6CAAyB,CAAC;AACnD,eAAO,MAAM,WAAW,4GAAwB,CAAC;AAEjD,eAAO,MAAM,aAAa,8JAUxB,CAAC;AAGH,eAAO,MAAM,aAAa,2FAyCxB,CAAC;AAGH,eAAO,MAAM,YAAY,EAAE,KAAK,CAAC,EAAE,CAAC,iBAAiB,CAEpD,CAAC;AAGF,eAAO,MAAM,YAAY,EAAE,KAAK,CAAC,EAAE,CAAC,iBAAiB,CAEpD,CAAC;AAGF,eAAO,MAAM,UAAU,EAAE,KAAK,CAAC,EAAE,CAAC,eAAe,CAEhD,CAAC;AAGF,eAAO,MAAM,WAAW,oKAUtB,CAAC;AAGH,eAAO,MAAM,iBAAiB,8KAU5B,CAAC"}
|
|
@@ -22,7 +22,7 @@ const DrawerOverlay = React.forwardRef(({ className, ...props }, ref) => /* @__P
|
|
|
22
22
|
}
|
|
23
23
|
));
|
|
24
24
|
DrawerOverlay.displayName = DialogPrimitive.Overlay.displayName;
|
|
25
|
-
const DrawerContent = React.forwardRef(({ className, children, side = "right", motion, ...props }, ref) => {
|
|
25
|
+
const DrawerContent = React.forwardRef(({ className, children, side = "right", size = "default", motion, showClose = true, ...props }, ref) => {
|
|
26
26
|
const globalMotion = useGlobalAnimation();
|
|
27
27
|
const { shouldAnimate, motionClass } = resolveMotion(motion, globalMotion);
|
|
28
28
|
return /* @__PURE__ */ jsxs(DrawerPortal, { children: [
|
|
@@ -33,14 +33,14 @@ const DrawerContent = React.forwardRef(({ className, children, side = "right", m
|
|
|
33
33
|
ref,
|
|
34
34
|
"data-slot": "drawer-content",
|
|
35
35
|
className: cn(
|
|
36
|
-
drawerContentVariants({ side }),
|
|
36
|
+
drawerContentVariants({ side, size }),
|
|
37
37
|
!shouldAnimate && "transition-none animate-none",
|
|
38
38
|
motionClass,
|
|
39
39
|
className
|
|
40
40
|
),
|
|
41
41
|
...props,
|
|
42
42
|
children: [
|
|
43
|
-
side === "bottom" && /* @__PURE__ */ jsx(
|
|
43
|
+
side === "bottom" && size !== "full" && /* @__PURE__ */ jsx(
|
|
44
44
|
"div",
|
|
45
45
|
{
|
|
46
46
|
"aria-hidden": "true",
|
|
@@ -49,7 +49,7 @@ const DrawerContent = React.forwardRef(({ className, children, side = "right", m
|
|
|
49
49
|
}
|
|
50
50
|
),
|
|
51
51
|
children,
|
|
52
|
-
/* @__PURE__ */ jsxs(
|
|
52
|
+
showClose && /* @__PURE__ */ jsxs(
|
|
53
53
|
DialogPrimitive.Close,
|
|
54
54
|
{
|
|
55
55
|
"data-slot": "drawer-close",
|
|
@@ -2,6 +2,7 @@ import { type VariantProps } from 'class-variance-authority';
|
|
|
2
2
|
export declare const drawerOverlayVariants: (props?: import("class-variance-authority/types").ClassProp | undefined) => string;
|
|
3
3
|
export declare const drawerContentVariants: (props?: ({
|
|
4
4
|
side?: "left" | "right" | "bottom" | "top" | null | undefined;
|
|
5
|
+
size?: "default" | "full" | null | undefined;
|
|
5
6
|
} & import("class-variance-authority/types").ClassProp) | undefined) => string;
|
|
6
7
|
export declare const drawerHeaderVariants: (props?: import("class-variance-authority/types").ClassProp | undefined) => string;
|
|
7
8
|
export declare const drawerFooterVariants: (props?: import("class-variance-authority/types").ClassProp | undefined) => string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Drawer.styles.d.ts","sourceRoot":"","sources":["../../../src/components/Drawer/Drawer.styles.ts"],"names":[],"mappings":"AAAA,OAAO,EAAO,KAAK,YAAY,EAAE,MAAM,0BAA0B,CAAC;AAElE,eAAO,MAAM,qBAAqB,oFAEjC,CAAC;AAEF,eAAO,MAAM,qBAAqB
|
|
1
|
+
{"version":3,"file":"Drawer.styles.d.ts","sourceRoot":"","sources":["../../../src/components/Drawer/Drawer.styles.ts"],"names":[],"mappings":"AAAA,OAAO,EAAO,KAAK,YAAY,EAAE,MAAM,0BAA0B,CAAC;AAElE,eAAO,MAAM,qBAAqB,oFAEjC,CAAC;AAEF,eAAO,MAAM,qBAAqB;;;8EAqBjC,CAAC;AAEF,eAAO,MAAM,oBAAoB,oFAEhC,CAAC;AAEF,eAAO,MAAM,oBAAoB,oFAEhC,CAAC;AAEF,gGAAgG;AAChG,eAAO,MAAM,kBAAkB,oFAAsE,CAAC;AAEtG,eAAO,MAAM,mBAAmB,oFAA2E,CAAC;AAE5G,eAAO,MAAM,yBAAyB,oFAA2D,CAAC;AAElG,MAAM,MAAM,qBAAqB,GAAG,YAAY,CAAC,OAAO,qBAAqB,CAAC,CAAC"}
|
|
@@ -12,10 +12,16 @@ const drawerContentVariants = cva(
|
|
|
12
12
|
bottom: "inset-x-0 bottom-0 border-t rounded-t-2xl max-h-[90dvh] pt-3 pb-[max(1.5rem,env(safe-area-inset-bottom))] data-[state=open]:animate-slide-in-from-bottom data-[state=closed]:animate-slide-out-to-bottom",
|
|
13
13
|
left: "inset-y-0 left-0 h-full w-3/4 max-w-sm border-r data-[state=open]:animate-slide-in-from-left data-[state=closed]:animate-slide-out-to-left",
|
|
14
14
|
right: "inset-y-0 right-0 h-full w-3/4 max-w-md border-l data-[state=open]:animate-slide-in-from-right data-[state=closed]:animate-slide-out-to-right"
|
|
15
|
+
},
|
|
16
|
+
/** `full` covers the whole viewport (mobile filter panels, full-screen pickers); the content lays itself out. */
|
|
17
|
+
size: {
|
|
18
|
+
default: "",
|
|
19
|
+
full: "inset-0 h-dvh max-h-none w-full max-w-none gap-0 rounded-none border-0 p-0 pt-0 pb-0"
|
|
15
20
|
}
|
|
16
21
|
},
|
|
17
22
|
defaultVariants: {
|
|
18
|
-
side: "right"
|
|
23
|
+
side: "right",
|
|
24
|
+
size: "default"
|
|
19
25
|
}
|
|
20
26
|
}
|
|
21
27
|
);
|
|
@@ -8,6 +8,8 @@ export interface DrawerContentProps extends React.ComponentPropsWithoutRef<typeo
|
|
|
8
8
|
* Motion transition control.
|
|
9
9
|
*/
|
|
10
10
|
motion?: MotionProp;
|
|
11
|
+
/** Render the corner close button (default true). Hide it when the content has its own. */
|
|
12
|
+
showClose?: boolean;
|
|
11
13
|
}
|
|
12
14
|
export type DrawerHeaderProps = React.HTMLAttributes<HTMLDivElement>;
|
|
13
15
|
export type DrawerFooterProps = React.HTMLAttributes<HTMLDivElement>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Drawer.types.d.ts","sourceRoot":"","sources":["../../../src/components/Drawer/Drawer.types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,KAAK,MAAM,OAAO,CAAC;AACpC,OAAO,KAAK,KAAK,eAAe,MAAM,wBAAwB,CAAC;AAC/D,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,iBAAiB,CAAC;AAC7D,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAErD,MAAM,MAAM,WAAW,GAAG,eAAe,CAAC,WAAW,CAAC;AAEtD,MAAM,WAAW,kBACf,SAAQ,KAAK,CAAC,wBAAwB,CAAC,OAAO,eAAe,CAAC,OAAO,CAAC,EACpE,qBAAqB;IACvB;;OAEG;IACH,MAAM,CAAC,EAAE,UAAU,CAAC;CACrB;AAED,MAAM,MAAM,iBAAiB,GAAG,KAAK,CAAC,cAAc,CAAC,cAAc,CAAC,CAAC;AACrE,MAAM,MAAM,iBAAiB,GAAG,KAAK,CAAC,cAAc,CAAC,cAAc,CAAC,CAAC;AACrE,MAAM,MAAM,eAAe,GAAG,KAAK,CAAC,cAAc,CAAC,cAAc,CAAC,CAAC"}
|
|
1
|
+
{"version":3,"file":"Drawer.types.d.ts","sourceRoot":"","sources":["../../../src/components/Drawer/Drawer.types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,KAAK,MAAM,OAAO,CAAC;AACpC,OAAO,KAAK,KAAK,eAAe,MAAM,wBAAwB,CAAC;AAC/D,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,iBAAiB,CAAC;AAC7D,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAErD,MAAM,MAAM,WAAW,GAAG,eAAe,CAAC,WAAW,CAAC;AAEtD,MAAM,WAAW,kBACf,SAAQ,KAAK,CAAC,wBAAwB,CAAC,OAAO,eAAe,CAAC,OAAO,CAAC,EACpE,qBAAqB;IACvB;;OAEG;IACH,MAAM,CAAC,EAAE,UAAU,CAAC;IACpB,2FAA2F;IAC3F,SAAS,CAAC,EAAE,OAAO,CAAC;CACrB;AAED,MAAM,MAAM,iBAAiB,GAAG,KAAK,CAAC,cAAc,CAAC,cAAc,CAAC,CAAC;AACrE,MAAM,MAAM,iBAAiB,GAAG,KAAK,CAAC,cAAc,CAAC,cAAc,CAAC,CAAC;AACrE,MAAM,MAAM,eAAe,GAAG,KAAK,CAAC,cAAc,CAAC,cAAc,CAAC,CAAC"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import type { FilterChip, FilterChipsProps } from './FilterChips.types';
|
|
3
|
+
/**
|
|
4
|
+
* The applied filters as removable chips, plus "Clear all". Wraps on large screens and scrolls
|
|
5
|
+
* sideways on phones so it never takes more than one row there. Renders nothing when empty.
|
|
6
|
+
*/
|
|
7
|
+
export declare function FilterChips<T extends FilterChip = FilterChip>({ chips, onRemove, onClearAll, clearAllLabel, removeLabel, className, }: FilterChipsProps<T>): React.JSX.Element | null;
|
|
8
|
+
//# sourceMappingURL=FilterChips.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"FilterChips.d.ts","sourceRoot":"","sources":["../../../src/components/FilterChips/FilterChips.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAG/B,OAAO,KAAK,EAAE,UAAU,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AAExE;;;GAGG;AACH,wBAAgB,WAAW,CAAC,CAAC,SAAS,UAAU,GAAG,UAAU,EAAE,EAC7D,KAAK,EACL,QAAQ,EACR,UAAU,EACV,aAA2B,EAC3B,WAA0C,EAC1C,SAAS,GACV,EAAE,gBAAgB,CAAC,CAAC,CAAC,4BA8BrB"}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsxs, jsx } from 'react/jsx-runtime';
|
|
3
|
+
import { cn } from '@timmbr/utils';
|
|
4
|
+
import { Chip } from '../Chip/Chip.js';
|
|
5
|
+
|
|
6
|
+
function FilterChips({
|
|
7
|
+
chips,
|
|
8
|
+
onRemove,
|
|
9
|
+
onClearAll,
|
|
10
|
+
clearAllLabel = "Clear all",
|
|
11
|
+
removeLabel = (label) => `Remove ${label}`,
|
|
12
|
+
className
|
|
13
|
+
}) {
|
|
14
|
+
if (chips.length === 0) return null;
|
|
15
|
+
return /* @__PURE__ */ jsxs(
|
|
16
|
+
"div",
|
|
17
|
+
{
|
|
18
|
+
"data-slot": "filter-chips",
|
|
19
|
+
className: cn(
|
|
20
|
+
"flex items-center gap-2 overflow-x-auto pb-1 [scrollbar-width:none] sm:flex-wrap sm:overflow-visible",
|
|
21
|
+
className
|
|
22
|
+
),
|
|
23
|
+
children: [
|
|
24
|
+
/* @__PURE__ */ jsx("ul", { className: "flex shrink-0 items-center gap-2 sm:flex-wrap", children: chips.map((chip) => /* @__PURE__ */ jsx("li", { className: "shrink-0", children: /* @__PURE__ */ jsx(Chip, { color: "primary", onRemove: () => onRemove(chip), removeLabel: removeLabel(String(chip.label)), children: chip.label }) }, chip.id)) }),
|
|
25
|
+
onClearAll && chips.length > 1 && /* @__PURE__ */ jsx(
|
|
26
|
+
"button",
|
|
27
|
+
{
|
|
28
|
+
type: "button",
|
|
29
|
+
onClick: onClearAll,
|
|
30
|
+
className: "shrink-0 rounded-sm px-1 font-sans text-body-3 font-semibold text-primary underline-offset-4 hover:underline focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring",
|
|
31
|
+
children: clearAllLabel
|
|
32
|
+
}
|
|
33
|
+
)
|
|
34
|
+
]
|
|
35
|
+
}
|
|
36
|
+
);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
export { FilterChips };
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type * as React from 'react';
|
|
2
|
+
export interface FilterChip {
|
|
3
|
+
/** Unique per chip, e.g. "material:teak" or "price". */
|
|
4
|
+
id: string;
|
|
5
|
+
label: React.ReactNode;
|
|
6
|
+
}
|
|
7
|
+
export interface FilterChipsProps<T extends FilterChip = FilterChip> {
|
|
8
|
+
chips: T[];
|
|
9
|
+
onRemove: (chip: T) => void;
|
|
10
|
+
/** Shown when more than one chip is applied. */
|
|
11
|
+
onClearAll?: () => void;
|
|
12
|
+
clearAllLabel?: string;
|
|
13
|
+
/** Accessible name of a chip's remove button. */
|
|
14
|
+
removeLabel?: (label: string) => string;
|
|
15
|
+
className?: string;
|
|
16
|
+
}
|
|
17
|
+
//# sourceMappingURL=FilterChips.types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"FilterChips.types.d.ts","sourceRoot":"","sources":["../../../src/components/FilterChips/FilterChips.types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,KAAK,MAAM,OAAO,CAAC;AAEpC,MAAM,WAAW,UAAU;IACzB,wDAAwD;IACxD,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,KAAK,CAAC,SAAS,CAAC;CACxB;AAED,MAAM,WAAW,gBAAgB,CAAC,CAAC,SAAS,UAAU,GAAG,UAAU;IACjE,KAAK,EAAE,CAAC,EAAE,CAAC;IACX,QAAQ,EAAE,CAAC,IAAI,EAAE,CAAC,KAAK,IAAI,CAAC;IAC5B,gDAAgD;IAChD,UAAU,CAAC,EAAE,MAAM,IAAI,CAAC;IACxB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,iDAAiD;IACjD,WAAW,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,MAAM,CAAC;IACxC,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/components/FilterChips/index.ts"],"names":[],"mappings":"AAAA,cAAc,eAAe,CAAC;AAC9B,cAAc,qBAAqB,CAAC"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import type { FilterDrawerLabels, FilterDrawerProps } from './FilterDrawer.types';
|
|
3
|
+
export declare const DEFAULT_FILTER_DRAWER_LABELS: FilterDrawerLabels;
|
|
4
|
+
/**
|
|
5
|
+
* Full-screen filter panel for phones: groups on the left (with how many options are picked),
|
|
6
|
+
* the active group's options on the right, and a sticky footer with "Clear all" and
|
|
7
|
+
* "Show N results". It edits a staged selection — nothing applies until the shopper taps Show,
|
|
8
|
+
* so the page behind doesn't reload on every tap; the page refreshes `total` as the draft
|
|
9
|
+
* changes and applies everything at once.
|
|
10
|
+
*/
|
|
11
|
+
export declare function FilterDrawer({ open, onOpenChange, groups, onToggle, price, onPriceChange, onClearAll, onApply, total, loading, labels: labelOverrides, searchThreshold, }: FilterDrawerProps): React.JSX.Element;
|
|
12
|
+
//# sourceMappingURL=FilterDrawer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"FilterDrawer.d.ts","sourceRoot":"","sources":["../../../src/components/FilterDrawer/FilterDrawer.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAsB/B,OAAO,KAAK,EAAE,kBAAkB,EAAE,iBAAiB,EAAE,MAAM,sBAAsB,CAAC;AAIlF,eAAO,MAAM,4BAA4B,EAAE,kBAM1C,CAAC;AAEF;;;;;;GAMG;AACH,wBAAgB,YAAY,CAAC,EAC3B,IAAI,EACJ,YAAY,EACZ,MAAM,EACN,QAAQ,EACR,KAAK,EACL,aAAa,EACb,UAAU,EACV,OAAO,EACP,KAAK,EACL,OAAe,EACf,MAAM,EAAE,cAAc,EACtB,eAAe,GAChB,EAAE,iBAAiB,qBAkJnB"}
|
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx, jsxs } from 'react/jsx-runtime';
|
|
3
|
+
import * as React from 'react';
|
|
4
|
+
import { X } from '@timmbr/icons';
|
|
5
|
+
import { cn } from '@timmbr/utils';
|
|
6
|
+
import { DEFAULT_FILTER_LABELS, FilterToggleRow, FilterPriceSlider, FilterOptionList } from '../FilterPanel/FilterPanel.js';
|
|
7
|
+
import { PRICE_GROUP_KEY } from '../FilterPanel/FilterPanel.types.js';
|
|
8
|
+
import { filterDrawerHeaderVariants, filterDrawerBadgeVariants, filterDrawerNavItemVariants, filterDrawerNavVariants, filterDrawerContentVariants, filterDrawerPanesVariants, filterDrawerFooterVariants } from './FilterDrawer.styles.js';
|
|
9
|
+
import { Drawer, DrawerContent, DrawerTitle, DrawerDescription, DrawerClose } from '../Drawer/Drawer.js';
|
|
10
|
+
import { Button } from '../Button/Button.js';
|
|
11
|
+
import { Spinner } from '../Spinner/Spinner.js';
|
|
12
|
+
|
|
13
|
+
const QUICK_GROUP_KEY = "__quick";
|
|
14
|
+
const DEFAULT_FILTER_DRAWER_LABELS = {
|
|
15
|
+
...DEFAULT_FILTER_LABELS,
|
|
16
|
+
quickFilters: "Quick filters",
|
|
17
|
+
clearAll: "Clear all",
|
|
18
|
+
close: "Close filters",
|
|
19
|
+
showResults: (total) => total === null ? "Show results" : `Show ${total} result${total === 1 ? "" : "s"}`
|
|
20
|
+
};
|
|
21
|
+
function FilterDrawer({
|
|
22
|
+
open,
|
|
23
|
+
onOpenChange,
|
|
24
|
+
groups,
|
|
25
|
+
onToggle,
|
|
26
|
+
price,
|
|
27
|
+
onPriceChange,
|
|
28
|
+
onClearAll,
|
|
29
|
+
onApply,
|
|
30
|
+
total,
|
|
31
|
+
loading = false,
|
|
32
|
+
labels: labelOverrides,
|
|
33
|
+
searchThreshold
|
|
34
|
+
}) {
|
|
35
|
+
const labels = { ...DEFAULT_FILTER_DRAWER_LABELS, ...labelOverrides };
|
|
36
|
+
const toggles = groups.filter((g) => g.display === "toggle");
|
|
37
|
+
const sections = groups.filter((g) => g.display !== "toggle");
|
|
38
|
+
const showPrice = !!price && price.step > 0 && price.max - price.min >= price.step;
|
|
39
|
+
const priceNarrowed = !!price?.value && (price.value[0] > price.min || price.value[1] < price.max);
|
|
40
|
+
const nav = [
|
|
41
|
+
...toggles.length ? [
|
|
42
|
+
{
|
|
43
|
+
key: QUICK_GROUP_KEY,
|
|
44
|
+
label: labels.quickFilters,
|
|
45
|
+
picked: toggles.filter((g) => g.options[0]?.selected).length
|
|
46
|
+
}
|
|
47
|
+
] : [],
|
|
48
|
+
...showPrice ? [{ key: PRICE_GROUP_KEY, label: labels.price, picked: priceNarrowed ? 1 : 0 }] : [],
|
|
49
|
+
...sections.map((g) => ({
|
|
50
|
+
key: g.key,
|
|
51
|
+
label: g.label,
|
|
52
|
+
picked: g.options.filter((o) => o.selected).length
|
|
53
|
+
}))
|
|
54
|
+
];
|
|
55
|
+
const [active, setActive] = React.useState(nav[0]?.key);
|
|
56
|
+
const activeKey = nav.some((n) => n.key === active) ? active : nav[0]?.key;
|
|
57
|
+
const activeGroup = sections.find((g) => g.key === activeKey);
|
|
58
|
+
const anyPicked = nav.some((n) => n.picked > 0);
|
|
59
|
+
const baseId = React.useId();
|
|
60
|
+
const tabId = (key) => `${baseId}-tab-${key}`;
|
|
61
|
+
const panelId = `${baseId}-panel`;
|
|
62
|
+
const tabRefs = React.useRef(/* @__PURE__ */ new Map());
|
|
63
|
+
const onTabKeyDown = (event) => {
|
|
64
|
+
const current = nav.findIndex((n) => n.key === activeKey);
|
|
65
|
+
let next = null;
|
|
66
|
+
if (event.key === "ArrowDown") next = (current + 1) % nav.length;
|
|
67
|
+
else if (event.key === "ArrowUp") next = (current - 1 + nav.length) % nav.length;
|
|
68
|
+
else if (event.key === "Home") next = 0;
|
|
69
|
+
else if (event.key === "End") next = nav.length - 1;
|
|
70
|
+
if (next === null || !nav[next]) return;
|
|
71
|
+
event.preventDefault();
|
|
72
|
+
setActive(nav[next].key);
|
|
73
|
+
tabRefs.current.get(nav[next].key)?.focus();
|
|
74
|
+
};
|
|
75
|
+
return /* @__PURE__ */ jsx(Drawer, { open, onOpenChange, children: /* @__PURE__ */ jsxs(DrawerContent, { side: "bottom", size: "full", showClose: false, children: [
|
|
76
|
+
/* @__PURE__ */ jsxs("div", { className: filterDrawerHeaderVariants(), children: [
|
|
77
|
+
/* @__PURE__ */ jsx(DrawerTitle, { className: "text-h6", children: labels.title }),
|
|
78
|
+
/* @__PURE__ */ jsx(DrawerDescription, { className: "sr-only", children: labels.showResults(total) }),
|
|
79
|
+
/* @__PURE__ */ jsx(DrawerClose, { asChild: true, children: /* @__PURE__ */ jsx(Button, { variant: "ghost", size: "icon-sm", "aria-label": labels.close, children: /* @__PURE__ */ jsx(X, { className: "size-5" }) }) })
|
|
80
|
+
] }),
|
|
81
|
+
/* @__PURE__ */ jsxs("div", { className: filterDrawerPanesVariants(), children: [
|
|
82
|
+
/* @__PURE__ */ jsx("nav", { className: filterDrawerNavVariants(), "aria-label": labels.title, children: /* @__PURE__ */ jsx("ul", { role: "tablist", "aria-orientation": "vertical", children: nav.map((item) => /* @__PURE__ */ jsx("li", { role: "presentation", children: /* @__PURE__ */ jsxs(
|
|
83
|
+
"button",
|
|
84
|
+
{
|
|
85
|
+
ref: (node) => {
|
|
86
|
+
if (node) tabRefs.current.set(item.key, node);
|
|
87
|
+
else tabRefs.current.delete(item.key);
|
|
88
|
+
},
|
|
89
|
+
type: "button",
|
|
90
|
+
role: "tab",
|
|
91
|
+
id: tabId(item.key),
|
|
92
|
+
"aria-selected": item.key === activeKey,
|
|
93
|
+
"aria-controls": panelId,
|
|
94
|
+
tabIndex: item.key === activeKey ? 0 : -1,
|
|
95
|
+
className: filterDrawerNavItemVariants({ active: item.key === activeKey }),
|
|
96
|
+
onClick: () => setActive(item.key),
|
|
97
|
+
onKeyDown: onTabKeyDown,
|
|
98
|
+
children: [
|
|
99
|
+
/* @__PURE__ */ jsx("span", { className: "min-w-0 break-words", children: item.label }),
|
|
100
|
+
item.picked > 0 && /* @__PURE__ */ jsx("span", { className: filterDrawerBadgeVariants(), children: item.picked })
|
|
101
|
+
]
|
|
102
|
+
}
|
|
103
|
+
) }, item.key)) }) }),
|
|
104
|
+
/* @__PURE__ */ jsxs(
|
|
105
|
+
"div",
|
|
106
|
+
{
|
|
107
|
+
id: panelId,
|
|
108
|
+
role: "tabpanel",
|
|
109
|
+
"aria-labelledby": activeKey ? tabId(activeKey) : void 0,
|
|
110
|
+
className: filterDrawerContentVariants(),
|
|
111
|
+
children: [
|
|
112
|
+
activeKey === QUICK_GROUP_KEY && /* @__PURE__ */ jsx("div", { className: "flex flex-col gap-5", children: toggles.map((group) => /* @__PURE__ */ jsx(FilterToggleRow, { group, onToggle }, group.key)) }),
|
|
113
|
+
activeKey === PRICE_GROUP_KEY && price && /* @__PURE__ */ jsx("div", { className: "pt-2", children: /* @__PURE__ */ jsx(
|
|
114
|
+
FilterPriceSlider,
|
|
115
|
+
{
|
|
116
|
+
price: { ...price, onApply: () => void 0, onReset: () => void 0 },
|
|
117
|
+
labels,
|
|
118
|
+
showActions: false,
|
|
119
|
+
onValueChange: (min, max) => onPriceChange?.(min, max)
|
|
120
|
+
}
|
|
121
|
+
) }),
|
|
122
|
+
activeGroup && /* @__PURE__ */ jsx(
|
|
123
|
+
FilterOptionList,
|
|
124
|
+
{
|
|
125
|
+
group: activeGroup,
|
|
126
|
+
onToggle,
|
|
127
|
+
limit: Number.POSITIVE_INFINITY,
|
|
128
|
+
searchThreshold,
|
|
129
|
+
labels
|
|
130
|
+
},
|
|
131
|
+
activeGroup.key
|
|
132
|
+
)
|
|
133
|
+
]
|
|
134
|
+
}
|
|
135
|
+
)
|
|
136
|
+
] }),
|
|
137
|
+
/* @__PURE__ */ jsxs("div", { className: filterDrawerFooterVariants(), children: [
|
|
138
|
+
/* @__PURE__ */ jsx(Button, { variant: "outline", className: "flex-1", onClick: onClearAll, disabled: !anyPicked, children: labels.clearAll }),
|
|
139
|
+
/* @__PURE__ */ jsxs(
|
|
140
|
+
Button,
|
|
141
|
+
{
|
|
142
|
+
variant: "primary",
|
|
143
|
+
className: cn("flex-[2]"),
|
|
144
|
+
onClick: onApply,
|
|
145
|
+
disabled: total === 0,
|
|
146
|
+
"aria-live": "polite",
|
|
147
|
+
children: [
|
|
148
|
+
loading && /* @__PURE__ */ jsx(Spinner, { size: "sm", className: "mr-2", "aria-hidden": "true" }),
|
|
149
|
+
labels.showResults(total)
|
|
150
|
+
]
|
|
151
|
+
}
|
|
152
|
+
)
|
|
153
|
+
] })
|
|
154
|
+
] }) });
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
export { DEFAULT_FILTER_DRAWER_LABELS, FilterDrawer };
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export declare const filterDrawerHeaderVariants: (props?: import("class-variance-authority/types").ClassProp | undefined) => string;
|
|
2
|
+
export declare const filterDrawerPanesVariants: (props?: import("class-variance-authority/types").ClassProp | undefined) => string;
|
|
3
|
+
/** Left pane: the list of groups. */
|
|
4
|
+
export declare const filterDrawerNavVariants: (props?: import("class-variance-authority/types").ClassProp | undefined) => string;
|
|
5
|
+
export declare const filterDrawerNavItemVariants: (props?: ({
|
|
6
|
+
active?: boolean | null | undefined;
|
|
7
|
+
} & import("class-variance-authority/types").ClassProp) | undefined) => string;
|
|
8
|
+
export declare const filterDrawerBadgeVariants: (props?: import("class-variance-authority/types").ClassProp | undefined) => string;
|
|
9
|
+
/** Right pane: the active group's options. */
|
|
10
|
+
export declare const filterDrawerContentVariants: (props?: import("class-variance-authority/types").ClassProp | undefined) => string;
|
|
11
|
+
export declare const filterDrawerFooterVariants: (props?: import("class-variance-authority/types").ClassProp | undefined) => string;
|
|
12
|
+
//# sourceMappingURL=FilterDrawer.styles.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"FilterDrawer.styles.d.ts","sourceRoot":"","sources":["../../../src/components/FilterDrawer/FilterDrawer.styles.ts"],"names":[],"mappings":"AAEA,eAAO,MAAM,0BAA0B,oFAEtC,CAAC;AAEF,eAAO,MAAM,yBAAyB,oFAA6B,CAAC;AAEpE,qCAAqC;AACrC,eAAO,MAAM,uBAAuB,oFAEnC,CAAC;AAEF,eAAO,MAAM,2BAA2B;;8EAWvC,CAAC;AAEF,eAAO,MAAM,yBAAyB,oFAErC,CAAC;AAEF,8CAA8C;AAC9C,eAAO,MAAM,2BAA2B,oFAAqE,CAAC;AAE9G,eAAO,MAAM,0BAA0B,oFAEtC,CAAC"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { cva } from 'class-variance-authority';
|
|
2
|
+
|
|
3
|
+
const filterDrawerHeaderVariants = cva(
|
|
4
|
+
"flex shrink-0 items-center justify-between gap-2 border-b border-grey-200 px-4 py-3"
|
|
5
|
+
);
|
|
6
|
+
const filterDrawerPanesVariants = cva("flex min-h-0 flex-1");
|
|
7
|
+
const filterDrawerNavVariants = cva(
|
|
8
|
+
"w-36 shrink-0 overflow-y-auto overscroll-contain border-r border-grey-200 bg-grey-100"
|
|
9
|
+
);
|
|
10
|
+
const filterDrawerNavItemVariants = cva(
|
|
11
|
+
"flex w-full items-center justify-between gap-2 border-l-4 px-3 py-4 text-left text-body-3 font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-inset focus-visible:ring-ring",
|
|
12
|
+
{
|
|
13
|
+
variants: {
|
|
14
|
+
active: {
|
|
15
|
+
true: "border-primary bg-grey-50 text-grey-950",
|
|
16
|
+
false: "border-transparent text-grey-700 hover:text-grey-950"
|
|
17
|
+
}
|
|
18
|
+
},
|
|
19
|
+
defaultVariants: { active: false }
|
|
20
|
+
}
|
|
21
|
+
);
|
|
22
|
+
const filterDrawerBadgeVariants = cva(
|
|
23
|
+
"inline-flex min-w-5 items-center justify-center rounded-full bg-primary px-1.5 text-caption font-semibold text-primary-foreground"
|
|
24
|
+
);
|
|
25
|
+
const filterDrawerContentVariants = cva("min-w-0 flex-1 overflow-y-auto overscroll-contain px-4 py-4");
|
|
26
|
+
const filterDrawerFooterVariants = cva(
|
|
27
|
+
"flex shrink-0 items-center gap-3 border-t border-grey-200 bg-grey-50 px-4 pt-3 pb-[max(0.75rem,env(safe-area-inset-bottom))]"
|
|
28
|
+
);
|
|
29
|
+
|
|
30
|
+
export { filterDrawerBadgeVariants, filterDrawerContentVariants, filterDrawerFooterVariants, filterDrawerHeaderVariants, filterDrawerNavItemVariants, filterDrawerNavVariants, filterDrawerPanesVariants };
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import type { FilterGroup, FilterPanelLabels, FilterPriceConfig } from '../FilterPanel/FilterPanel.types';
|
|
2
|
+
export interface FilterDrawerLabels extends FilterPanelLabels {
|
|
3
|
+
/** Left-pane entry holding the yes/no toggles. */
|
|
4
|
+
quickFilters: string;
|
|
5
|
+
clearAll: string;
|
|
6
|
+
close: string;
|
|
7
|
+
/** Apply button, e.g. (n) => `Show ${n} results`; `null` while the count is unknown. */
|
|
8
|
+
showResults: (total: number | null) => string;
|
|
9
|
+
}
|
|
10
|
+
export interface FilterDrawerProps {
|
|
11
|
+
open: boolean;
|
|
12
|
+
onOpenChange: (open: boolean) => void;
|
|
13
|
+
/** The staged (not yet applied) selection: the drawer edits a draft, the page applies it. */
|
|
14
|
+
groups: FilterGroup[];
|
|
15
|
+
onToggle: (key: string, value: string) => void;
|
|
16
|
+
/** Staged price; changes arrive through `onPriceChange`, not Apply/Reset. */
|
|
17
|
+
price?: Omit<FilterPriceConfig, 'onApply' | 'onReset'>;
|
|
18
|
+
onPriceChange?: (min: number, max: number) => void;
|
|
19
|
+
onClearAll: () => void;
|
|
20
|
+
onApply: () => void;
|
|
21
|
+
/** Results the staged selection would show (null while counting). */
|
|
22
|
+
total: number | null;
|
|
23
|
+
/** True while counts are being fetched for the staged selection. */
|
|
24
|
+
loading?: boolean;
|
|
25
|
+
labels?: Partial<FilterDrawerLabels>;
|
|
26
|
+
searchThreshold?: number;
|
|
27
|
+
}
|
|
28
|
+
//# sourceMappingURL=FilterDrawer.types.d.ts.map
|