@duestel/ui 0.1.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/README.md +110 -0
- package/dist/components/accordion/Accordion.d.ts +34 -0
- package/dist/components/accordion/Accordion.js +54 -0
- package/dist/components/accordion/Accordion.js.map +1 -0
- package/dist/components/accordion/index.d.ts +1 -0
- package/dist/components/accordion/index.js +2 -0
- package/dist/components/alert-dialog/AlertDialog.d.ts +53 -0
- package/dist/components/alert-dialog/AlertDialog.js +69 -0
- package/dist/components/alert-dialog/AlertDialog.js.map +1 -0
- package/dist/components/alert-dialog/index.d.ts +1 -0
- package/dist/components/alert-dialog/index.js +2 -0
- package/dist/components/autocomplete/Autocomplete.d.ts +90 -0
- package/dist/components/autocomplete/Autocomplete.js +137 -0
- package/dist/components/autocomplete/Autocomplete.js.map +1 -0
- package/dist/components/autocomplete/index.d.ts +1 -0
- package/dist/components/autocomplete/index.js +2 -0
- package/dist/components/avatar/Avatar.d.ts +44 -0
- package/dist/components/avatar/Avatar.js +45 -0
- package/dist/components/avatar/Avatar.js.map +1 -0
- package/dist/components/avatar/index.d.ts +2 -0
- package/dist/components/avatar/index.js +2 -0
- package/dist/components/badge/Badge.d.ts +43 -0
- package/dist/components/badge/Badge.js +32 -0
- package/dist/components/badge/Badge.js.map +1 -0
- package/dist/components/badge/index.d.ts +2 -0
- package/dist/components/badge/index.js +2 -0
- package/dist/components/button/Button.d.ts +60 -0
- package/dist/components/button/Button.js +61 -0
- package/dist/components/button/Button.js.map +1 -0
- package/dist/components/button/index.d.ts +1 -0
- package/dist/components/button/index.js +2 -0
- package/dist/components/carousel/Carousel.d.ts +32 -0
- package/dist/components/carousel/Carousel.js +113 -0
- package/dist/components/carousel/Carousel.js.map +1 -0
- package/dist/components/carousel/index.d.ts +1 -0
- package/dist/components/carousel/index.js +2 -0
- package/dist/components/checkbox/Checkbox.d.ts +64 -0
- package/dist/components/checkbox/Checkbox.js +59 -0
- package/dist/components/checkbox/Checkbox.js.map +1 -0
- package/dist/components/checkbox/index.d.ts +1 -0
- package/dist/components/checkbox/index.js +2 -0
- package/dist/components/collapsible/Collapsible.d.ts +28 -0
- package/dist/components/collapsible/Collapsible.js +40 -0
- package/dist/components/collapsible/Collapsible.js.map +1 -0
- package/dist/components/collapsible/index.d.ts +1 -0
- package/dist/components/collapsible/index.js +2 -0
- package/dist/components/combobox/Combobox.d.ts +113 -0
- package/dist/components/combobox/Combobox.js +189 -0
- package/dist/components/combobox/Combobox.js.map +1 -0
- package/dist/components/combobox/index.d.ts +1 -0
- package/dist/components/combobox/index.js +2 -0
- package/dist/components/command/Command.d.ts +37 -0
- package/dist/components/command/Command.js +90 -0
- package/dist/components/command/Command.js.map +1 -0
- package/dist/components/command/index.d.ts +1 -0
- package/dist/components/command/index.js +2 -0
- package/dist/components/context-menu/ContextMenu.d.ts +76 -0
- package/dist/components/context-menu/ContextMenu.js +132 -0
- package/dist/components/context-menu/ContextMenu.js.map +1 -0
- package/dist/components/context-menu/index.d.ts +1 -0
- package/dist/components/context-menu/index.js +2 -0
- package/dist/components/data-table/DataTable.d.ts +32 -0
- package/dist/components/data-table/DataTable.js +102 -0
- package/dist/components/data-table/DataTable.js.map +1 -0
- package/dist/components/data-table/Table.d.ts +51 -0
- package/dist/components/data-table/Table.js +69 -0
- package/dist/components/data-table/Table.js.map +1 -0
- package/dist/components/data-table/index.d.ts +3 -0
- package/dist/components/data-table/index.js +3 -0
- package/dist/components/date-picker/DatePicker.d.ts +63 -0
- package/dist/components/date-picker/DatePicker.js +247 -0
- package/dist/components/date-picker/DatePicker.js.map +1 -0
- package/dist/components/date-picker/index.d.ts +2 -0
- package/dist/components/date-picker/index.js +2 -0
- package/dist/components/dialog/Dialog.d.ts +59 -0
- package/dist/components/dialog/Dialog.js +71 -0
- package/dist/components/dialog/Dialog.js.map +1 -0
- package/dist/components/dialog/index.d.ts +1 -0
- package/dist/components/dialog/index.js +2 -0
- package/dist/components/drawer/Drawer.d.ts +93 -0
- package/dist/components/drawer/Drawer.js +106 -0
- package/dist/components/drawer/Drawer.js.map +1 -0
- package/dist/components/drawer/index.d.ts +1 -0
- package/dist/components/drawer/index.js +2 -0
- package/dist/components/form/Field.d.ts +52 -0
- package/dist/components/form/Field.js +54 -0
- package/dist/components/form/Field.js.map +1 -0
- package/dist/components/form/Fieldset.d.ts +24 -0
- package/dist/components/form/Fieldset.js +24 -0
- package/dist/components/form/Fieldset.js.map +1 -0
- package/dist/components/form/Form.d.ts +18 -0
- package/dist/components/form/Form.js +14 -0
- package/dist/components/form/Form.js.map +1 -0
- package/dist/components/form/Input.d.ts +33 -0
- package/dist/components/form/Input.js +99 -0
- package/dist/components/form/Input.js.map +1 -0
- package/dist/components/form/app-form.d.ts +71 -0
- package/dist/components/form/app-form.js +95 -0
- package/dist/components/form/app-form.js.map +1 -0
- package/dist/components/form/index.d.ts +5 -0
- package/dist/components/form/index.js +6 -0
- package/dist/components/hotkeys/Kbd.d.ts +20 -0
- package/dist/components/hotkeys/Kbd.js +31 -0
- package/dist/components/hotkeys/Kbd.js.map +1 -0
- package/dist/components/hotkeys/hotkeys.d.ts +14 -0
- package/dist/components/hotkeys/hotkeys.js +2 -0
- package/dist/components/hotkeys/index.d.ts +2 -0
- package/dist/components/hotkeys/index.js +3 -0
- package/dist/components/menu/Menu.d.ts +84 -0
- package/dist/components/menu/Menu.js +142 -0
- package/dist/components/menu/Menu.js.map +1 -0
- package/dist/components/menu/index.d.ts +1 -0
- package/dist/components/menu/index.js +2 -0
- package/dist/components/menubar/Menubar.d.ts +87 -0
- package/dist/components/menubar/Menubar.js +142 -0
- package/dist/components/menubar/Menubar.js.map +1 -0
- package/dist/components/menubar/index.d.ts +1 -0
- package/dist/components/menubar/index.js +2 -0
- package/dist/components/meter/Meter.d.ts +33 -0
- package/dist/components/meter/Meter.js +45 -0
- package/dist/components/meter/Meter.js.map +1 -0
- package/dist/components/meter/index.d.ts +1 -0
- package/dist/components/meter/index.js +2 -0
- package/dist/components/navigation-menu/NavigationMenu.d.ts +81 -0
- package/dist/components/navigation-menu/NavigationMenu.js +112 -0
- package/dist/components/navigation-menu/NavigationMenu.js.map +1 -0
- package/dist/components/navigation-menu/index.d.ts +1 -0
- package/dist/components/navigation-menu/index.js +2 -0
- package/dist/components/number-field/NumberField.d.ts +53 -0
- package/dist/components/number-field/NumberField.js +72 -0
- package/dist/components/number-field/NumberField.js.map +1 -0
- package/dist/components/number-field/index.d.ts +1 -0
- package/dist/components/number-field/index.js +2 -0
- package/dist/components/otp-field/OtpField.d.ts +33 -0
- package/dist/components/otp-field/OtpField.js +31 -0
- package/dist/components/otp-field/OtpField.js.map +1 -0
- package/dist/components/otp-field/index.d.ts +1 -0
- package/dist/components/otp-field/index.js +2 -0
- package/dist/components/pagination/Pagination.d.ts +17 -0
- package/dist/components/pagination/Pagination.js +75 -0
- package/dist/components/pagination/Pagination.js.map +1 -0
- package/dist/components/pagination/index.d.ts +1 -0
- package/dist/components/pagination/index.js +2 -0
- package/dist/components/popover/Popover.d.ts +73 -0
- package/dist/components/popover/Popover.js +97 -0
- package/dist/components/popover/Popover.js.map +1 -0
- package/dist/components/popover/index.d.ts +1 -0
- package/dist/components/popover/index.js +2 -0
- package/dist/components/preview-card/PreviewCard.d.ts +60 -0
- package/dist/components/preview-card/PreviewCard.js +83 -0
- package/dist/components/preview-card/PreviewCard.js.map +1 -0
- package/dist/components/preview-card/index.d.ts +1 -0
- package/dist/components/preview-card/index.js +2 -0
- package/dist/components/progress/Progress.d.ts +36 -0
- package/dist/components/progress/Progress.js +45 -0
- package/dist/components/progress/Progress.js.map +1 -0
- package/dist/components/progress/index.d.ts +1 -0
- package/dist/components/progress/index.js +2 -0
- package/dist/components/radio/Radio.d.ts +39 -0
- package/dist/components/radio/Radio.js +39 -0
- package/dist/components/radio/Radio.js.map +1 -0
- package/dist/components/radio/index.d.ts +1 -0
- package/dist/components/radio/index.js +2 -0
- package/dist/components/resizable/Resizable.d.ts +35 -0
- package/dist/components/resizable/Resizable.js +38 -0
- package/dist/components/resizable/Resizable.js.map +1 -0
- package/dist/components/resizable/index.d.ts +1 -0
- package/dist/components/resizable/index.js +2 -0
- package/dist/components/scroll-area/ScrollArea.d.ts +37 -0
- package/dist/components/scroll-area/ScrollArea.js +52 -0
- package/dist/components/scroll-area/ScrollArea.js.map +1 -0
- package/dist/components/scroll-area/index.d.ts +1 -0
- package/dist/components/scroll-area/index.js +2 -0
- package/dist/components/select/Select.d.ts +94 -0
- package/dist/components/select/Select.js +151 -0
- package/dist/components/select/Select.js.map +1 -0
- package/dist/components/select/index.d.ts +1 -0
- package/dist/components/select/index.js +2 -0
- package/dist/components/separator/Separator.d.ts +29 -0
- package/dist/components/separator/Separator.js +20 -0
- package/dist/components/separator/Separator.js.map +1 -0
- package/dist/components/separator/index.d.ts +1 -0
- package/dist/components/separator/index.js +2 -0
- package/dist/components/slider/Slider.d.ts +53 -0
- package/dist/components/slider/Slider.js +70 -0
- package/dist/components/slider/Slider.js.map +1 -0
- package/dist/components/slider/index.d.ts +1 -0
- package/dist/components/slider/index.js +2 -0
- package/dist/components/switch/Switch.d.ts +28 -0
- package/dist/components/switch/Switch.js +31 -0
- package/dist/components/switch/Switch.js.map +1 -0
- package/dist/components/switch/index.d.ts +1 -0
- package/dist/components/switch/index.js +2 -0
- package/dist/components/tabs/Tabs.d.ts +41 -0
- package/dist/components/tabs/Tabs.js +45 -0
- package/dist/components/tabs/Tabs.js.map +1 -0
- package/dist/components/tabs/index.d.ts +1 -0
- package/dist/components/tabs/index.js +2 -0
- package/dist/components/toast/Toast.d.ts +70 -0
- package/dist/components/toast/Toast.js +95 -0
- package/dist/components/toast/Toast.js.map +1 -0
- package/dist/components/toast/index.d.ts +1 -0
- package/dist/components/toast/index.js +2 -0
- package/dist/components/toggle/Toggle.d.ts +38 -0
- package/dist/components/toggle/Toggle.js +30 -0
- package/dist/components/toggle/Toggle.js.map +1 -0
- package/dist/components/toggle/index.d.ts +1 -0
- package/dist/components/toggle/index.js +2 -0
- package/dist/components/toolbar/Toolbar.d.ts +50 -0
- package/dist/components/toolbar/Toolbar.js +59 -0
- package/dist/components/toolbar/Toolbar.js.map +1 -0
- package/dist/components/toolbar/index.d.ts +1 -0
- package/dist/components/toolbar/index.js +2 -0
- package/dist/components/tooltip/Tooltip.d.ts +58 -0
- package/dist/components/tooltip/Tooltip.js +57 -0
- package/dist/components/tooltip/Tooltip.js.map +1 -0
- package/dist/components/tooltip/index.d.ts +1 -0
- package/dist/components/tooltip/index.js +2 -0
- package/dist/index.d.ts +60 -0
- package/dist/index.js +48 -0
- package/dist/lib/cn.d.ts +3 -0
- package/dist/lib/cn.js +29 -0
- package/dist/lib/cn.js.map +1 -0
- package/dist/styles.css +2 -0
- package/dist/theme.css +109 -0
- package/package.json +131 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Table.js","names":[],"sources":["../../../src/components/data-table/Table.tsx"],"sourcesContent":["import { cn } from '#/lib/cn'\n\nimport type { ComponentProps, ReactNode } from 'react'\n\n/**\n * Table — ported from port/core/ui/components/data-table (see CLAUDE.md):\n * auto-layout table in an overflow-auto shell, surface-container header\n * (body-medium, 500), zebra body rows (odd rows surface-container/50),\n * 16/12px cell padding, body-medium cells on body-small base.\n *\n * Compound API mirrors the port:\n * <Table>\n * <Table.Head>\n * <Table.Row>\n * <Table.HeaderCell>Name</Table.HeaderCell>\n * </Table.Row>\n * </Table.Head>\n * <Table.Body>\n * <Table.Row>\n * <Table.Cell>…</Table.Cell>\n * </Table.Row>\n * </Table.Body>\n * </Table>\n *\n * <TextContainer width=\"w-[300px]\"> wraps long cell copy at a fixed width.\n * Cells accept `data` as an alternative to children (port API).\n */\n\nfunction TableRoot({ className, children, ...props }: ComponentProps<'table'>) {\n return (\n <div className=\"overflow-auto\">\n <table\n className={cn(\n 'w-full table-auto overflow-clip text-body-small text-on-surface',\n className,\n )}\n {...props}\n >\n {children}\n </table>\n </div>\n )\n}\n\nfunction Head({ className, ...props }: ComponentProps<'thead'>) {\n return (\n <thead className={cn('bg-surface-container text-body-medium', className)} {...props} />\n )\n}\n\nfunction Body({ className, ...props }: ComponentProps<'tbody'>) {\n return <tbody className={cn('text-body-medium', className)} {...props} />\n}\n\nfunction Row({ className, ...props }: ComponentProps<'tr'>) {\n return (\n <tr className={cn('overflow-hidden odd:bg-surface-container/50', className)} {...props} />\n )\n}\n\ntype CellProps = ComponentProps<'th'> & {\n /** Cell content, port API alternative to children. */\n data?: ReactNode\n}\n\nfunction HeaderCell({ className, children, data, ...props }: CellProps) {\n return (\n <th\n className={cn('min-w-max overflow-hidden px-4 py-3 text-left font-medium', className)}\n {...props}\n >\n <div className=\"flex h-full w-full min-w-max flex-wrap\">{children ?? data}</div>\n </th>\n )\n}\n\nfunction Cell({ className, children, data, ...props }: ComponentProps<'td'> & { data?: ReactNode }) {\n return (\n <td className={cn('min-w-max px-4 py-3 pr-8', className)} {...props}>\n <span className=\"flex sm:min-w-max\">{children ?? data}</span>\n </td>\n )\n}\n\ntype TextContainerProps = ComponentProps<'div'> & {\n /** Tailwind width class for the text column. @default 'w-[300px]' */\n width?: string\n data?: ReactNode\n}\n\n/** Fixed-width wrapper for long cell copy (port API). */\nfunction TextContainer({ className, children, data, width, ...props }: TextContainerProps) {\n return (\n <div className={cn('flex', width ?? 'w-[300px]', className)} {...props}>\n {children ?? data}\n </div>\n )\n}\n\nexport const Table = Object.assign(TableRoot, {\n Head,\n Body,\n Row,\n HeaderCell,\n Cell,\n})\nexport { TextContainer }\n"],"mappings":";;;AA4BA,SAAS,EAAU,EAAE,cAAW,aAAU,GAAG,KAAkC;CAC7E,OACE,kBAAC,OAAD;EAAK,WAAU;YACb,kBAAC,SAAD;GACE,WAAW,EACT,mEACA,CACF;GACA,GAAI;GAEH;EACI,CAAA;CACJ,CAAA;AAET;AAEA,SAAS,EAAK,EAAE,cAAW,GAAG,KAAkC;CAC9D,OACE,kBAAC,SAAD;EAAO,WAAW,EAAG,yCAAyC,CAAS;EAAG,GAAI;CAAQ,CAAA;AAE1F;AAEA,SAAS,EAAK,EAAE,cAAW,GAAG,KAAkC;CAC9D,OAAO,kBAAC,SAAD;EAAO,WAAW,EAAG,oBAAoB,CAAS;EAAG,GAAI;CAAQ,CAAA;AAC1E;AAEA,SAAS,EAAI,EAAE,cAAW,GAAG,KAA+B;CAC1D,OACE,kBAAC,MAAD;EAAI,WAAW,EAAG,+CAA+C,CAAS;EAAG,GAAI;CAAQ,CAAA;AAE7F;AAOA,SAAS,EAAW,EAAE,cAAW,aAAU,SAAM,GAAG,KAAoB;CACtE,OACE,kBAAC,MAAD;EACE,WAAW,EAAG,6DAA6D,CAAS;EACpF,GAAI;YAEJ,kBAAC,OAAD;GAAK,WAAU;aAA0C,KAAY;EAAU,CAAA;CAC7E,CAAA;AAER;AAEA,SAAS,EAAK,EAAE,cAAW,aAAU,SAAM,GAAG,KAAsD;CAClG,OACE,kBAAC,MAAD;EAAI,WAAW,EAAG,4BAA4B,CAAS;EAAG,GAAI;YAC5D,kBAAC,QAAD;GAAM,WAAU;aAAqB,KAAY;EAAW,CAAA;CAC1D,CAAA;AAER;AASA,SAAS,EAAc,EAAE,cAAW,aAAU,SAAM,UAAO,GAAG,KAA6B;CACzF,OACE,kBAAC,OAAD;EAAK,WAAW,EAAG,QAAQ,KAAS,aAAa,CAAS;EAAG,GAAI;YAC9D,KAAY;CACV,CAAA;AAET;AAEA,IAAa,IAAQ,OAAO,OAAO,GAAW;CAC5C;CACA;CACA;CACA;CACA;AACF,CAAC"}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import { Input } from '../../../components/form/Input';
|
|
2
|
+
import { ComponentProps, ReactNode } from 'react';
|
|
3
|
+
type CalendarBounds = {
|
|
4
|
+
/** Earliest selectable day (inclusive). */
|
|
5
|
+
min?: Date;
|
|
6
|
+
/** Latest selectable day (inclusive). */
|
|
7
|
+
max?: Date;
|
|
8
|
+
/** Disable arbitrary days (e.g. weekends, booked dates). */
|
|
9
|
+
disabledDate?: (date: Date) => boolean;
|
|
10
|
+
locale?: string;
|
|
11
|
+
};
|
|
12
|
+
type CalendarProps = CalendarBounds & {
|
|
13
|
+
selected: Date | null;
|
|
14
|
+
onSelect: (date: Date) => void;
|
|
15
|
+
};
|
|
16
|
+
/** Single-date month grid — usable standalone (inline calendars, widgets). */
|
|
17
|
+
declare function Calendar({ selected, onSelect, ...bounds }: CalendarProps): import("react").JSX.Element;
|
|
18
|
+
type DateRange = {
|
|
19
|
+
from: Date | null;
|
|
20
|
+
to: Date | null;
|
|
21
|
+
};
|
|
22
|
+
type RangeCalendarProps = CalendarBounds & {
|
|
23
|
+
range: DateRange;
|
|
24
|
+
onPick: (date: Date) => void;
|
|
25
|
+
};
|
|
26
|
+
/** Range month grid: endpoint circles + secondary-container band between. */
|
|
27
|
+
declare function RangeCalendar({ range, onPick, ...bounds }: RangeCalendarProps): import("react").JSX.Element;
|
|
28
|
+
type PickerBaseProps = CalendarBounds & {
|
|
29
|
+
label?: ReactNode;
|
|
30
|
+
disabled?: boolean;
|
|
31
|
+
name?: string;
|
|
32
|
+
/** @default { year: 'numeric', month: 'short', day: 'numeric' } */
|
|
33
|
+
formatOptions?: Intl.DateTimeFormatOptions;
|
|
34
|
+
/** Field variant, port skins. @default 'outlined' */
|
|
35
|
+
variant?: ComponentProps<typeof Input>['variant'];
|
|
36
|
+
className?: string;
|
|
37
|
+
};
|
|
38
|
+
type DatePickerProps = PickerBaseProps & {
|
|
39
|
+
/** Controlled selected date. */
|
|
40
|
+
value?: Date | null;
|
|
41
|
+
/** Uncontrolled initial date. */
|
|
42
|
+
defaultValue?: Date | null;
|
|
43
|
+
onChange?: (date: Date) => void;
|
|
44
|
+
};
|
|
45
|
+
declare function DatePicker({ value, defaultValue, onChange, label, disabled, name, locale, formatOptions, variant, className, ...bounds }: DatePickerProps): import("react").JSX.Element;
|
|
46
|
+
type DateRangePickerProps = PickerBaseProps & {
|
|
47
|
+
/** Controlled range ({ from, to } — either side may be null mid-selection). */
|
|
48
|
+
value?: DateRange;
|
|
49
|
+
/** Uncontrolled initial range. */
|
|
50
|
+
defaultValue?: DateRange;
|
|
51
|
+
/** Fired once both ends are picked. */
|
|
52
|
+
onChange?: (range: {
|
|
53
|
+
from: Date;
|
|
54
|
+
to: Date;
|
|
55
|
+
}) => void;
|
|
56
|
+
};
|
|
57
|
+
/**
|
|
58
|
+
* Range variant: first click sets the start, second completes the range
|
|
59
|
+
* (swapping if picked backwards) and closes; a third starts over.
|
|
60
|
+
*/
|
|
61
|
+
declare function DateRangePicker({ value, defaultValue, onChange, label, disabled, name, locale, formatOptions, variant, className, ...bounds }: DateRangePickerProps): import("react").JSX.Element;
|
|
62
|
+
export { DatePicker, DateRangePicker, Calendar, RangeCalendar };
|
|
63
|
+
export type { DateRange };
|
|
@@ -0,0 +1,247 @@
|
|
|
1
|
+
import { cn as e } from "../../lib/cn.js";
|
|
2
|
+
import { Button as t } from "../button/Button.js";
|
|
3
|
+
import { Input as n } from "../form/Input.js";
|
|
4
|
+
import { Popover as r } from "../popover/Popover.js";
|
|
5
|
+
import { CalendarDays as i, ChevronDown as a, ChevronLeft as o, ChevronRight as s } from "lucide-react";
|
|
6
|
+
import { jsx as c, jsxs as l } from "react/jsx-runtime";
|
|
7
|
+
import { useMemo as u, useState as d } from "react";
|
|
8
|
+
//#region src/components/date-picker/DatePicker.tsx
|
|
9
|
+
function f(e) {
|
|
10
|
+
return new Date(e.getFullYear(), e.getMonth(), 1);
|
|
11
|
+
}
|
|
12
|
+
function p(e) {
|
|
13
|
+
return new Date(e.getFullYear(), e.getMonth(), e.getDate());
|
|
14
|
+
}
|
|
15
|
+
function m(e, t) {
|
|
16
|
+
return !!e && e.getFullYear() === t.getFullYear() && e.getMonth() === t.getMonth() && e.getDate() === t.getDate();
|
|
17
|
+
}
|
|
18
|
+
function h({ locale: n, min: r, max: i, disabledDate: h, initialMonth: g, dayState: _, onPick: v }) {
|
|
19
|
+
let [y, b] = d(() => f(g)), [x, S] = d("days"), C = /* @__PURE__ */ new Date(), w = y.getFullYear(), T = y.getMonth(), E = u(() => new Intl.DateTimeFormat(n, {
|
|
20
|
+
month: "long",
|
|
21
|
+
year: "numeric"
|
|
22
|
+
}).format(y), [n, y]), D = u(() => {
|
|
23
|
+
let e = new Intl.DateTimeFormat(n, { weekday: "narrow" });
|
|
24
|
+
return Array.from({ length: 7 }, (t, n) => e.format(new Date(2023, 0, 1 + n)));
|
|
25
|
+
}, [n]), O = r ? p(r) : null, k = i ? p(i) : null, A = (e) => O !== null && e < O || k !== null && e > k || !!h?.(e);
|
|
26
|
+
if (x === "years") {
|
|
27
|
+
let n = w - (w % 12 + 12) % 12, r = Array.from({ length: 12 }, (e, t) => n + t);
|
|
28
|
+
return /* @__PURE__ */ l("div", {
|
|
29
|
+
className: "flex w-[280px] flex-col gap-2",
|
|
30
|
+
children: [/* @__PURE__ */ l("div", {
|
|
31
|
+
className: "flex items-center justify-between",
|
|
32
|
+
children: [
|
|
33
|
+
/* @__PURE__ */ c(t.Icon, {
|
|
34
|
+
variant: "standard",
|
|
35
|
+
"aria-label": "Previous years",
|
|
36
|
+
disabled: O !== null && n - 1 < O.getFullYear(),
|
|
37
|
+
onClick: () => b(new Date(w - 12, T, 1)),
|
|
38
|
+
children: /* @__PURE__ */ c(o, {})
|
|
39
|
+
}),
|
|
40
|
+
/* @__PURE__ */ l("span", {
|
|
41
|
+
className: "text-title-small text-on-surface",
|
|
42
|
+
children: [
|
|
43
|
+
n,
|
|
44
|
+
" – ",
|
|
45
|
+
n + 11
|
|
46
|
+
]
|
|
47
|
+
}),
|
|
48
|
+
/* @__PURE__ */ c(t.Icon, {
|
|
49
|
+
variant: "standard",
|
|
50
|
+
"aria-label": "Next years",
|
|
51
|
+
disabled: k !== null && n + 12 > k.getFullYear(),
|
|
52
|
+
onClick: () => b(new Date(w + 12, T, 1)),
|
|
53
|
+
children: /* @__PURE__ */ c(s, {})
|
|
54
|
+
})
|
|
55
|
+
]
|
|
56
|
+
}), /* @__PURE__ */ c("div", {
|
|
57
|
+
className: "grid grid-cols-3 gap-1",
|
|
58
|
+
children: r.map((t) => /* @__PURE__ */ c("button", {
|
|
59
|
+
type: "button",
|
|
60
|
+
disabled: O !== null && t < O.getFullYear() || k !== null && t > k.getFullYear(),
|
|
61
|
+
onClick: () => {
|
|
62
|
+
b(new Date(t, T, 1)), S("days");
|
|
63
|
+
},
|
|
64
|
+
className: e("flex h-9 cursor-pointer items-center justify-center rounded-full", "text-body-small text-on-surface transition-colors hover:bg-on-surface/[0.08]", "focus-visible:outline-2 focus-visible:-outline-offset-2 focus-visible:outline-primary", "disabled:cursor-not-allowed disabled:opacity-[0.38] disabled:hover:bg-transparent", t === w && "bg-primary text-on-primary hover:bg-primary-hover"),
|
|
65
|
+
children: t
|
|
66
|
+
}, t))
|
|
67
|
+
})]
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
let j = new Date(w, T, 1).getDay(), M = new Date(w, T + 1, 0).getDate(), N = [...Array.from({ length: j }, () => null), ...Array.from({ length: M }, (e, t) => t + 1)], P = O !== null && new Date(w, T, 0) < O, F = k !== null && new Date(w, T + 1, 1) > k;
|
|
71
|
+
return /* @__PURE__ */ l("div", {
|
|
72
|
+
className: "flex w-[280px] flex-col gap-2",
|
|
73
|
+
children: [/* @__PURE__ */ l("div", {
|
|
74
|
+
className: "flex items-center justify-between",
|
|
75
|
+
children: [
|
|
76
|
+
/* @__PURE__ */ c(t.Icon, {
|
|
77
|
+
variant: "standard",
|
|
78
|
+
"aria-label": "Previous month",
|
|
79
|
+
disabled: P,
|
|
80
|
+
onClick: () => b(new Date(w, T - 1, 1)),
|
|
81
|
+
children: /* @__PURE__ */ c(o, {})
|
|
82
|
+
}),
|
|
83
|
+
/* @__PURE__ */ l("button", {
|
|
84
|
+
type: "button",
|
|
85
|
+
onClick: () => S("years"),
|
|
86
|
+
className: e("flex h-8 cursor-pointer items-center gap-1 rounded-full px-2", "text-title-small text-on-surface transition-colors hover:bg-on-surface/[0.08]", "focus-visible:outline-2 focus-visible:-outline-offset-2 focus-visible:outline-primary"),
|
|
87
|
+
children: [E, /* @__PURE__ */ c(a, {
|
|
88
|
+
"aria-hidden": !0,
|
|
89
|
+
className: "size-4 text-on-surface-variant"
|
|
90
|
+
})]
|
|
91
|
+
}),
|
|
92
|
+
/* @__PURE__ */ c(t.Icon, {
|
|
93
|
+
variant: "standard",
|
|
94
|
+
"aria-label": "Next month",
|
|
95
|
+
disabled: F,
|
|
96
|
+
onClick: () => b(new Date(w, T + 1, 1)),
|
|
97
|
+
children: /* @__PURE__ */ c(s, {})
|
|
98
|
+
})
|
|
99
|
+
]
|
|
100
|
+
}), /* @__PURE__ */ l("div", {
|
|
101
|
+
className: "grid grid-cols-7",
|
|
102
|
+
children: [D.map((e, t) => /* @__PURE__ */ c("span", {
|
|
103
|
+
className: "flex size-10 items-center justify-center text-body-small text-on-surface-variant",
|
|
104
|
+
children: e
|
|
105
|
+
}, t)), N.map((t, n) => {
|
|
106
|
+
if (t === null) return /* @__PURE__ */ c("span", {}, `pad-${n}`);
|
|
107
|
+
let r = new Date(w, T, t), { selected: i, inRange: a } = _(r);
|
|
108
|
+
return /* @__PURE__ */ c("button", {
|
|
109
|
+
type: "button",
|
|
110
|
+
disabled: A(r),
|
|
111
|
+
onClick: () => v(r),
|
|
112
|
+
className: e("flex size-10 cursor-pointer items-center justify-center rounded-full", "text-body-small text-on-surface transition-colors", "hover:bg-on-surface/[0.08]", "focus-visible:outline-2 focus-visible:-outline-offset-2 focus-visible:outline-primary", "disabled:cursor-not-allowed disabled:opacity-[0.38] disabled:hover:bg-transparent", m(C, r) && !i && !a && "border border-outline text-primary", a && "rounded-none bg-secondary-container text-on-secondary-container hover:bg-secondary-container-hover", i && "rounded-full border-0 bg-primary text-on-primary hover:bg-primary-hover"),
|
|
113
|
+
children: t
|
|
114
|
+
}, t);
|
|
115
|
+
})]
|
|
116
|
+
})]
|
|
117
|
+
});
|
|
118
|
+
}
|
|
119
|
+
function g({ selected: e, onSelect: t, ...n }) {
|
|
120
|
+
return /* @__PURE__ */ c(h, {
|
|
121
|
+
...n,
|
|
122
|
+
initialMonth: e ?? /* @__PURE__ */ new Date(),
|
|
123
|
+
dayState: (t) => ({ selected: m(e, t) }),
|
|
124
|
+
onPick: t
|
|
125
|
+
});
|
|
126
|
+
}
|
|
127
|
+
function _({ range: e, onPick: t, ...n }) {
|
|
128
|
+
return /* @__PURE__ */ c(h, {
|
|
129
|
+
...n,
|
|
130
|
+
initialMonth: e.from ?? /* @__PURE__ */ new Date(),
|
|
131
|
+
dayState: (t) => ({
|
|
132
|
+
selected: m(e.from, t) || m(e.to, t),
|
|
133
|
+
inRange: !!e.from && !!e.to && t > p(e.from) && t < p(e.to)
|
|
134
|
+
}),
|
|
135
|
+
onPick: t
|
|
136
|
+
});
|
|
137
|
+
}
|
|
138
|
+
function v({ label: e, text: t, variant: r = "outlined", disabled: a, name: o }) {
|
|
139
|
+
return /* @__PURE__ */ c(n, {
|
|
140
|
+
variant: r,
|
|
141
|
+
label: e,
|
|
142
|
+
value: t,
|
|
143
|
+
readOnly: !0,
|
|
144
|
+
disabled: a,
|
|
145
|
+
name: o,
|
|
146
|
+
tabIndex: -1,
|
|
147
|
+
className: "pointer-events-none",
|
|
148
|
+
rightElement: /* @__PURE__ */ c(i, {
|
|
149
|
+
size: 24,
|
|
150
|
+
"aria-hidden": !0
|
|
151
|
+
})
|
|
152
|
+
});
|
|
153
|
+
}
|
|
154
|
+
function y(e, t) {
|
|
155
|
+
return u(() => new Intl.DateTimeFormat(e, t ?? {
|
|
156
|
+
year: "numeric",
|
|
157
|
+
month: "short",
|
|
158
|
+
day: "numeric"
|
|
159
|
+
}), [e, t]);
|
|
160
|
+
}
|
|
161
|
+
function b({ open: t, onOpenChange: n, field: i, disabled: a, className: o, children: s }) {
|
|
162
|
+
return /* @__PURE__ */ l(r.Root, {
|
|
163
|
+
open: t,
|
|
164
|
+
onOpenChange: n,
|
|
165
|
+
children: [/* @__PURE__ */ c(r.Trigger, {
|
|
166
|
+
disabled: a,
|
|
167
|
+
nativeButton: !1,
|
|
168
|
+
render: /* @__PURE__ */ c("div", { className: e("w-full cursor-pointer rounded-small text-left outline-none", "focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-primary", o) }),
|
|
169
|
+
children: i
|
|
170
|
+
}), /* @__PURE__ */ c(r.Portal, { children: /* @__PURE__ */ c(r.Positioner, {
|
|
171
|
+
sideOffset: 4,
|
|
172
|
+
align: "start",
|
|
173
|
+
children: /* @__PURE__ */ c(r.Popup, {
|
|
174
|
+
className: "p-3",
|
|
175
|
+
children: s
|
|
176
|
+
})
|
|
177
|
+
}) })]
|
|
178
|
+
});
|
|
179
|
+
}
|
|
180
|
+
function x({ value: e, defaultValue: t, onChange: n, label: r, disabled: i, name: a, locale: o, formatOptions: s, variant: l, className: u, ...f }) {
|
|
181
|
+
let [p, m] = d(!1), [h, _] = d(t ?? null), x = e === void 0 ? h : e, S = y(o, s);
|
|
182
|
+
return /* @__PURE__ */ c(b, {
|
|
183
|
+
open: p,
|
|
184
|
+
onOpenChange: m,
|
|
185
|
+
disabled: i,
|
|
186
|
+
className: u,
|
|
187
|
+
field: /* @__PURE__ */ c(v, {
|
|
188
|
+
label: r,
|
|
189
|
+
text: x ? S.format(x) : "",
|
|
190
|
+
variant: l,
|
|
191
|
+
disabled: i,
|
|
192
|
+
name: a
|
|
193
|
+
}),
|
|
194
|
+
children: /* @__PURE__ */ c(g, {
|
|
195
|
+
selected: x,
|
|
196
|
+
locale: o,
|
|
197
|
+
...f,
|
|
198
|
+
onSelect: (e) => {
|
|
199
|
+
_(e), n?.(e), m(!1);
|
|
200
|
+
}
|
|
201
|
+
})
|
|
202
|
+
});
|
|
203
|
+
}
|
|
204
|
+
function S({ value: e, defaultValue: t, onChange: n, label: r, disabled: i, name: a, locale: o, formatOptions: s, variant: l, className: u, ...f }) {
|
|
205
|
+
let [p, m] = d(!1), [h, g] = d(t ?? {
|
|
206
|
+
from: null,
|
|
207
|
+
to: null
|
|
208
|
+
}), x = e === void 0 ? h : e, S = y(o, s), C = x.from && x.to ? S.formatRange(x.from, x.to) : x.from ? `${S.format(x.from)} – ` : "", w = (e) => {
|
|
209
|
+
let t;
|
|
210
|
+
t = !x.from || x.to ? {
|
|
211
|
+
from: e,
|
|
212
|
+
to: null
|
|
213
|
+
} : e < x.from ? {
|
|
214
|
+
from: e,
|
|
215
|
+
to: x.from
|
|
216
|
+
} : {
|
|
217
|
+
from: x.from,
|
|
218
|
+
to: e
|
|
219
|
+
}, g(t), t.from && t.to && (n?.({
|
|
220
|
+
from: t.from,
|
|
221
|
+
to: t.to
|
|
222
|
+
}), m(!1));
|
|
223
|
+
};
|
|
224
|
+
return /* @__PURE__ */ c(b, {
|
|
225
|
+
open: p,
|
|
226
|
+
onOpenChange: m,
|
|
227
|
+
disabled: i,
|
|
228
|
+
className: u,
|
|
229
|
+
field: /* @__PURE__ */ c(v, {
|
|
230
|
+
label: r,
|
|
231
|
+
text: C,
|
|
232
|
+
variant: l,
|
|
233
|
+
disabled: i,
|
|
234
|
+
name: a
|
|
235
|
+
}),
|
|
236
|
+
children: /* @__PURE__ */ c(_, {
|
|
237
|
+
range: x,
|
|
238
|
+
locale: o,
|
|
239
|
+
...f,
|
|
240
|
+
onPick: w
|
|
241
|
+
})
|
|
242
|
+
});
|
|
243
|
+
}
|
|
244
|
+
//#endregion
|
|
245
|
+
export { g as Calendar, x as DatePicker, S as DateRangePicker, _ as RangeCalendar };
|
|
246
|
+
|
|
247
|
+
//# sourceMappingURL=DatePicker.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"DatePicker.js","names":[],"sources":["../../../src/components/date-picker/DatePicker.tsx"],"sourcesContent":["import { useMemo, useState } from 'react'\nimport { CalendarDays, ChevronDown, ChevronLeft, ChevronRight } from 'lucide-react'\nimport { Button } from '#/components/button'\nimport { Input } from '#/components/form/Input'\nimport { Popover } from '#/components/popover'\nimport { cn } from '#/lib/cn'\n\nimport type { ComponentProps, ReactNode } from 'react'\n\n/**\n * Date pickers — M3 docked date picker built on this catalog's primitives:\n * the port text field (Input) as the anchor and Popover for the calendar\n * overlay (https://m3.material.io/components/date-pickers — docked variant).\n *\n * <DatePicker label=\"Date\" onChange={(date) => …} />\n * <DateRangePicker label=\"Stay\" onChange={({ from, to }) => …} />\n *\n * Shared month view: 40px circular day targets, selected day = primary\n * circle, today = outlined, range days = secondary-container band, year-grid\n * navigation via the month label, min/max bounds + disabledDate predicate.\n * Calendar / RangeCalendar are exported standalone for inline use.\n */\n\nfunction startOfMonth(d: Date) {\n return new Date(d.getFullYear(), d.getMonth(), 1)\n}\n\nfunction stripTime(d: Date) {\n return new Date(d.getFullYear(), d.getMonth(), d.getDate())\n}\n\nfunction isSameDay(a: Date | null | undefined, b: Date) {\n return (\n !!a &&\n a.getFullYear() === b.getFullYear() &&\n a.getMonth() === b.getMonth() &&\n a.getDate() === b.getDate()\n )\n}\n\ntype CalendarBounds = {\n /** Earliest selectable day (inclusive). */\n min?: Date\n /** Latest selectable day (inclusive). */\n max?: Date\n /** Disable arbitrary days (e.g. weekends, booked dates). */\n disabledDate?: (date: Date) => boolean\n locale?: string\n}\n\ntype MonthViewProps = CalendarBounds & {\n initialMonth: Date\n dayState: (date: Date) => { selected?: boolean; inRange?: boolean }\n onPick: (date: Date) => void\n}\n\n/** Month grid + year-grid navigation shared by Calendar and RangeCalendar. */\nfunction MonthView({\n locale,\n min,\n max,\n disabledDate,\n initialMonth,\n dayState,\n onPick,\n}: MonthViewProps) {\n const [view, setView] = useState(() => startOfMonth(initialMonth))\n const [mode, setMode] = useState<'days' | 'years'>('days')\n const today = new Date()\n const year = view.getFullYear()\n const month = view.getMonth()\n\n const monthLabel = useMemo(\n () => new Intl.DateTimeFormat(locale, { month: 'long', year: 'numeric' }).format(view),\n [locale, view],\n )\n const weekdays = useMemo(() => {\n const fmt = new Intl.DateTimeFormat(locale, { weekday: 'narrow' })\n // 2023-01-01 was a Sunday.\n return Array.from({ length: 7 }, (_, i) => fmt.format(new Date(2023, 0, 1 + i)))\n }, [locale])\n\n const minDay = min ? stripTime(min) : null\n const maxDay = max ? stripTime(max) : null\n const isDayDisabled = (t: Date) =>\n (minDay !== null && t < minDay) || (maxDay !== null && t > maxDay) || !!disabledDate?.(t)\n\n // Year-grid navigation (M3 docked: month label opens year selection).\n if (mode === 'years') {\n const base = year - ((year % 12) + 12) % 12\n const years = Array.from({ length: 12 }, (_, i) => base + i)\n return (\n <div className=\"flex w-[280px] flex-col gap-2\">\n <div className=\"flex items-center justify-between\">\n <Button.Icon\n variant=\"standard\"\n aria-label=\"Previous years\"\n disabled={minDay !== null && base - 1 < minDay.getFullYear()}\n onClick={() => setView(new Date(year - 12, month, 1))}\n >\n <ChevronLeft />\n </Button.Icon>\n <span className=\"text-title-small text-on-surface\">\n {base} – {base + 11}\n </span>\n <Button.Icon\n variant=\"standard\"\n aria-label=\"Next years\"\n disabled={maxDay !== null && base + 12 > maxDay.getFullYear()}\n onClick={() => setView(new Date(year + 12, month, 1))}\n >\n <ChevronRight />\n </Button.Icon>\n </div>\n <div className=\"grid grid-cols-3 gap-1\">\n {years.map((y) => {\n const disabled =\n (minDay !== null && y < minDay.getFullYear()) ||\n (maxDay !== null && y > maxDay.getFullYear())\n return (\n <button\n key={y}\n type=\"button\"\n disabled={disabled}\n onClick={() => {\n setView(new Date(y, month, 1))\n setMode('days')\n }}\n className={cn(\n 'flex h-9 cursor-pointer items-center justify-center rounded-full',\n 'text-body-small text-on-surface transition-colors hover:bg-on-surface/[0.08]',\n 'focus-visible:outline-2 focus-visible:-outline-offset-2 focus-visible:outline-primary',\n 'disabled:cursor-not-allowed disabled:opacity-[0.38] disabled:hover:bg-transparent',\n y === year && 'bg-primary text-on-primary hover:bg-primary-hover',\n )}\n >\n {y}\n </button>\n )\n })}\n </div>\n </div>\n )\n }\n\n const firstDow = new Date(year, month, 1).getDay()\n const daysInMonth = new Date(year, month + 1, 0).getDate()\n const cells: Array<number | null> = [\n ...Array.from({ length: firstDow }, () => null),\n ...Array.from({ length: daysInMonth }, (_, i) => i + 1),\n ]\n const prevDisabled = minDay !== null && new Date(year, month, 0) < minDay\n const nextDisabled = maxDay !== null && new Date(year, month + 1, 1) > maxDay\n\n return (\n <div className=\"flex w-[280px] flex-col gap-2\">\n <div className=\"flex items-center justify-between\">\n <Button.Icon\n variant=\"standard\"\n aria-label=\"Previous month\"\n disabled={prevDisabled}\n onClick={() => setView(new Date(year, month - 1, 1))}\n >\n <ChevronLeft />\n </Button.Icon>\n <button\n type=\"button\"\n onClick={() => setMode('years')}\n className={cn(\n 'flex h-8 cursor-pointer items-center gap-1 rounded-full px-2',\n 'text-title-small text-on-surface transition-colors hover:bg-on-surface/[0.08]',\n 'focus-visible:outline-2 focus-visible:-outline-offset-2 focus-visible:outline-primary',\n )}\n >\n {monthLabel}\n <ChevronDown aria-hidden className=\"size-4 text-on-surface-variant\" />\n </button>\n <Button.Icon\n variant=\"standard\"\n aria-label=\"Next month\"\n disabled={nextDisabled}\n onClick={() => setView(new Date(year, month + 1, 1))}\n >\n <ChevronRight />\n </Button.Icon>\n </div>\n\n <div className=\"grid grid-cols-7\">\n {weekdays.map((d, i) => (\n <span\n key={i}\n className=\"flex size-10 items-center justify-center text-body-small text-on-surface-variant\"\n >\n {d}\n </span>\n ))}\n {cells.map((day, i) => {\n if (day === null) return <span key={`pad-${i}`} />\n const t = new Date(year, month, day)\n const { selected, inRange } = dayState(t)\n const disabled = isDayDisabled(t)\n return (\n <button\n key={day}\n type=\"button\"\n disabled={disabled}\n onClick={() => onPick(t)}\n className={cn(\n 'flex size-10 cursor-pointer items-center justify-center rounded-full',\n 'text-body-small text-on-surface transition-colors',\n 'hover:bg-on-surface/[0.08]',\n 'focus-visible:outline-2 focus-visible:-outline-offset-2 focus-visible:outline-primary',\n 'disabled:cursor-not-allowed disabled:opacity-[0.38] disabled:hover:bg-transparent',\n isSameDay(today, t) && !selected && !inRange && 'border border-outline text-primary',\n inRange &&\n 'rounded-none bg-secondary-container text-on-secondary-container hover:bg-secondary-container-hover',\n selected && 'rounded-full border-0 bg-primary text-on-primary hover:bg-primary-hover',\n )}\n >\n {day}\n </button>\n )\n })}\n </div>\n </div>\n )\n}\n\ntype CalendarProps = CalendarBounds & {\n selected: Date | null\n onSelect: (date: Date) => void\n}\n\n/** Single-date month grid — usable standalone (inline calendars, widgets). */\nfunction Calendar({ selected, onSelect, ...bounds }: CalendarProps) {\n return (\n <MonthView\n {...bounds}\n initialMonth={selected ?? new Date()}\n dayState={(t) => ({ selected: isSameDay(selected, t) })}\n onPick={onSelect}\n />\n )\n}\n\ntype DateRange = { from: Date | null; to: Date | null }\n\ntype RangeCalendarProps = CalendarBounds & {\n range: DateRange\n onPick: (date: Date) => void\n}\n\n/** Range month grid: endpoint circles + secondary-container band between. */\nfunction RangeCalendar({ range, onPick, ...bounds }: RangeCalendarProps) {\n return (\n <MonthView\n {...bounds}\n initialMonth={range.from ?? new Date()}\n dayState={(t) => ({\n selected: isSameDay(range.from, t) || isSameDay(range.to, t),\n inRange:\n !!range.from &&\n !!range.to &&\n t > stripTime(range.from) &&\n t < stripTime(range.to),\n })}\n onPick={onPick}\n />\n )\n}\n\ntype PickerFieldProps = {\n label?: ReactNode\n text: string\n variant?: ComponentProps<typeof Input>['variant']\n disabled?: boolean\n name?: string\n}\n\n/** Display-only port text field used as the popover anchor. */\nfunction PickerField({ label, text, variant = 'outlined', disabled, name }: PickerFieldProps) {\n return (\n <Input\n variant={variant}\n label={label}\n value={text}\n readOnly\n disabled={disabled}\n name={name}\n tabIndex={-1}\n className=\"pointer-events-none\"\n rightElement={<CalendarDays size={24} aria-hidden />}\n />\n )\n}\n\ntype PickerBaseProps = CalendarBounds & {\n label?: ReactNode\n disabled?: boolean\n name?: string\n /** @default { year: 'numeric', month: 'short', day: 'numeric' } */\n formatOptions?: Intl.DateTimeFormatOptions\n /** Field variant, port skins. @default 'outlined' */\n variant?: ComponentProps<typeof Input>['variant']\n className?: string\n}\n\nfunction useDateFormatter(locale?: string, formatOptions?: Intl.DateTimeFormatOptions) {\n return useMemo(\n () =>\n new Intl.DateTimeFormat(\n locale,\n formatOptions ?? { year: 'numeric', month: 'short', day: 'numeric' },\n ),\n [locale, formatOptions],\n )\n}\n\ntype PickerShellProps = {\n open: boolean\n onOpenChange: (open: boolean) => void\n field: ReactNode\n disabled?: boolean\n className?: string\n children: ReactNode\n}\n\n/** Popover wiring shared by both pickers. */\nfunction PickerShell({ open, onOpenChange, field, disabled, className, children }: PickerShellProps) {\n return (\n <Popover.Root open={open} onOpenChange={onOpenChange}>\n <Popover.Trigger\n disabled={disabled}\n nativeButton={false}\n render={\n <div\n className={cn(\n // No UA focus ring (black); keyboard focus gets an M3 primary\n // ring via focus-visible — mouse clicks show nothing extra.\n 'w-full cursor-pointer rounded-small text-left outline-none',\n 'focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-primary',\n className,\n )}\n />\n }\n >\n {field}\n </Popover.Trigger>\n <Popover.Portal>\n <Popover.Positioner sideOffset={4} align=\"start\">\n <Popover.Popup className=\"p-3\">{children}</Popover.Popup>\n </Popover.Positioner>\n </Popover.Portal>\n </Popover.Root>\n )\n}\n\ntype DatePickerProps = PickerBaseProps & {\n /** Controlled selected date. */\n value?: Date | null\n /** Uncontrolled initial date. */\n defaultValue?: Date | null\n onChange?: (date: Date) => void\n}\n\nfunction DatePicker({\n value,\n defaultValue,\n onChange,\n label,\n disabled,\n name,\n locale,\n formatOptions,\n variant,\n className,\n ...bounds\n}: DatePickerProps) {\n const [open, setOpen] = useState(false)\n const [internal, setInternal] = useState<Date | null>(defaultValue ?? null)\n const selected = value !== undefined ? value : internal\n const formatter = useDateFormatter(locale, formatOptions)\n\n return (\n <PickerShell\n open={open}\n onOpenChange={setOpen}\n disabled={disabled}\n className={className}\n field={\n <PickerField\n label={label}\n text={selected ? formatter.format(selected) : ''}\n variant={variant}\n disabled={disabled}\n name={name}\n />\n }\n >\n <Calendar\n selected={selected}\n locale={locale}\n {...bounds}\n onSelect={(date) => {\n setInternal(date)\n onChange?.(date)\n setOpen(false)\n }}\n />\n </PickerShell>\n )\n}\n\ntype DateRangePickerProps = PickerBaseProps & {\n /** Controlled range ({ from, to } — either side may be null mid-selection). */\n value?: DateRange\n /** Uncontrolled initial range. */\n defaultValue?: DateRange\n /** Fired once both ends are picked. */\n onChange?: (range: { from: Date; to: Date }) => void\n}\n\n/**\n * Range variant: first click sets the start, second completes the range\n * (swapping if picked backwards) and closes; a third starts over.\n */\nfunction DateRangePicker({\n value,\n defaultValue,\n onChange,\n label,\n disabled,\n name,\n locale,\n formatOptions,\n variant,\n className,\n ...bounds\n}: DateRangePickerProps) {\n const [open, setOpen] = useState(false)\n const [internal, setInternal] = useState<DateRange>(defaultValue ?? { from: null, to: null })\n const range = value !== undefined ? value : internal\n const formatter = useDateFormatter(locale, formatOptions)\n\n const text =\n range.from && range.to\n ? formatter.formatRange(range.from, range.to)\n : range.from\n ? `${formatter.format(range.from)} – `\n : ''\n\n const handlePick = (date: Date) => {\n let next: DateRange\n if (!range.from || range.to) {\n next = { from: date, to: null }\n } else {\n next =\n date < range.from ? { from: date, to: range.from } : { from: range.from, to: date }\n }\n setInternal(next)\n if (next.from && next.to) {\n onChange?.({ from: next.from, to: next.to })\n setOpen(false)\n }\n }\n\n return (\n <PickerShell\n open={open}\n onOpenChange={setOpen}\n disabled={disabled}\n className={className}\n field={\n <PickerField label={label} text={text} variant={variant} disabled={disabled} name={name} />\n }\n >\n <RangeCalendar range={range} locale={locale} {...bounds} onPick={handlePick} />\n </PickerShell>\n )\n}\n\nexport { DatePicker, DateRangePicker, Calendar, RangeCalendar }\nexport type { DateRange }\n"],"mappings":"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"}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { Dialog as BaseDialog } from '@base-ui/react/dialog';
|
|
2
|
+
import { ComponentProps } from 'react';
|
|
3
|
+
/**
|
|
4
|
+
* Dialog — Material 3 styled wrapper over Base UI's headless Dialog.
|
|
5
|
+
* Behaviour/accessibility (focus trap, role="dialog", dismiss on backdrop
|
|
6
|
+
* click/Esc): Base UI (https://base-ui.com/react/components/dialog).
|
|
7
|
+
* Visuals: M3 dialog anatomy — scrim, extra-large corner, surface-container,
|
|
8
|
+
* headline-small title, body-medium supporting text, text-button actions.
|
|
9
|
+
* Same anatomy as AlertDialog, but dismissible.
|
|
10
|
+
* Design ref: port/core/ui/components/dialogs (see CLAUDE.md).
|
|
11
|
+
*
|
|
12
|
+
* Compound API mirrors Base UI:
|
|
13
|
+
* <Dialog.Root>
|
|
14
|
+
* <Dialog.Trigger>Open</Dialog.Trigger>
|
|
15
|
+
* <Dialog.Portal>
|
|
16
|
+
* <Dialog.Backdrop />
|
|
17
|
+
* <Dialog.Viewport>
|
|
18
|
+
* <Dialog.Popup>
|
|
19
|
+
* <Dialog.Title>Reset settings?</Dialog.Title>
|
|
20
|
+
* <Dialog.Description>This will restore the defaults.</Dialog.Description>
|
|
21
|
+
* <Dialog.Actions>
|
|
22
|
+
* <Dialog.Close>Cancel</Dialog.Close>
|
|
23
|
+
* <Dialog.Close>Reset</Dialog.Close>
|
|
24
|
+
* </Dialog.Actions>
|
|
25
|
+
* </Dialog.Popup>
|
|
26
|
+
* </Dialog.Viewport>
|
|
27
|
+
* </Dialog.Portal>
|
|
28
|
+
* </Dialog.Root>
|
|
29
|
+
*/
|
|
30
|
+
declare const Root: typeof BaseDialog.Root;
|
|
31
|
+
declare const Portal: import('react').ForwardRefExoticComponent<Omit<import('@base-ui/react').AlertDialogPortalProps, "ref"> & import('react').RefAttributes<HTMLDivElement>>;
|
|
32
|
+
/** Imperative handle for detached triggers — re-exported from Base UI. */
|
|
33
|
+
declare const Handle: typeof BaseDialog.Handle;
|
|
34
|
+
declare const createHandle: typeof BaseDialog.createHandle;
|
|
35
|
+
declare function Trigger({ className, ...props }: ComponentProps<typeof BaseDialog.Trigger>): import("react").JSX.Element;
|
|
36
|
+
declare function Backdrop({ className, ...props }: ComponentProps<typeof BaseDialog.Backdrop>): import("react").JSX.Element;
|
|
37
|
+
declare function Viewport({ className, ...props }: ComponentProps<typeof BaseDialog.Viewport>): import("react").JSX.Element;
|
|
38
|
+
declare function Popup({ className, ...props }: ComponentProps<typeof BaseDialog.Popup>): import("react").JSX.Element;
|
|
39
|
+
declare function Title({ className, ...props }: ComponentProps<typeof BaseDialog.Title>): import("react").JSX.Element;
|
|
40
|
+
declare function Description({ className, ...props }: ComponentProps<typeof BaseDialog.Description>): import("react").JSX.Element;
|
|
41
|
+
/** Trailing actions row (M3: right-aligned text buttons). */
|
|
42
|
+
declare function Actions({ className, ...props }: ComponentProps<'div'>): import("react").JSX.Element;
|
|
43
|
+
/** Closes the dialog; styled as an M3 text button — pair inside <Actions>. */
|
|
44
|
+
declare function Close({ className, ...props }: ComponentProps<typeof BaseDialog.Close>): import("react").JSX.Element;
|
|
45
|
+
export declare const Dialog: {
|
|
46
|
+
Root: typeof BaseDialog.Root;
|
|
47
|
+
Trigger: typeof Trigger;
|
|
48
|
+
Portal: import('react').ForwardRefExoticComponent<Omit<import('@base-ui/react').AlertDialogPortalProps, "ref"> & import('react').RefAttributes<HTMLDivElement>>;
|
|
49
|
+
Backdrop: typeof Backdrop;
|
|
50
|
+
Viewport: typeof Viewport;
|
|
51
|
+
Popup: typeof Popup;
|
|
52
|
+
Title: typeof Title;
|
|
53
|
+
Description: typeof Description;
|
|
54
|
+
Actions: typeof Actions;
|
|
55
|
+
Close: typeof Close;
|
|
56
|
+
Handle: typeof BaseDialog.Handle;
|
|
57
|
+
createHandle: typeof BaseDialog.createHandle;
|
|
58
|
+
};
|
|
59
|
+
export { Root, Trigger, Portal, Backdrop, Viewport, Popup, Title, Description, Actions, Close, Handle, createHandle, };
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import { cn as e } from "../../lib/cn.js";
|
|
2
|
+
import { jsx as t } from "react/jsx-runtime";
|
|
3
|
+
import { Dialog as n } from "@base-ui/react/dialog";
|
|
4
|
+
//#region src/components/dialog/Dialog.tsx
|
|
5
|
+
var r = n.Root, i = n.Portal, a = n.Handle, o = n.createHandle;
|
|
6
|
+
function s({ className: r, ...i }) {
|
|
7
|
+
return /* @__PURE__ */ t(n.Trigger, {
|
|
8
|
+
className: e(r),
|
|
9
|
+
...i
|
|
10
|
+
});
|
|
11
|
+
}
|
|
12
|
+
function c({ className: r, ...i }) {
|
|
13
|
+
return /* @__PURE__ */ t(n.Backdrop, {
|
|
14
|
+
className: e("fixed inset-0 z-40 bg-scrim transition-opacity duration-200 ease-out", "data-[ending-style]:opacity-0 data-[starting-style]:opacity-0", r),
|
|
15
|
+
...i
|
|
16
|
+
});
|
|
17
|
+
}
|
|
18
|
+
function l({ className: r, ...i }) {
|
|
19
|
+
return /* @__PURE__ */ t(n.Viewport, {
|
|
20
|
+
className: e("fixed inset-0 z-50 flex items-center justify-center p-4", r),
|
|
21
|
+
...i
|
|
22
|
+
});
|
|
23
|
+
}
|
|
24
|
+
function u({ className: r, ...i }) {
|
|
25
|
+
return /* @__PURE__ */ t(n.Popup, {
|
|
26
|
+
className: e("flex w-full min-w-[280px] max-w-[560px] flex-col gap-4", "rounded-extra-large bg-surface-container p-6 text-on-surface shadow-mm-3", "transition-all duration-200 ease-out focus:outline-none", "data-[starting-style]:scale-95 data-[starting-style]:opacity-0", "data-[ending-style]:scale-95 data-[ending-style]:opacity-0", r),
|
|
27
|
+
...i
|
|
28
|
+
});
|
|
29
|
+
}
|
|
30
|
+
function d({ className: r, ...i }) {
|
|
31
|
+
return /* @__PURE__ */ t(n.Title, {
|
|
32
|
+
className: e("m-0 text-headline-small text-on-surface", r),
|
|
33
|
+
...i
|
|
34
|
+
});
|
|
35
|
+
}
|
|
36
|
+
function f({ className: r, ...i }) {
|
|
37
|
+
return /* @__PURE__ */ t(n.Description, {
|
|
38
|
+
className: e("m-0 text-body-medium text-on-surface-variant", r),
|
|
39
|
+
...i
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
function p({ className: n, ...r }) {
|
|
43
|
+
return /* @__PURE__ */ t("div", {
|
|
44
|
+
className: e("mt-2 flex items-center justify-end gap-2", n),
|
|
45
|
+
...r
|
|
46
|
+
});
|
|
47
|
+
}
|
|
48
|
+
function m({ className: r, ...i }) {
|
|
49
|
+
return /* @__PURE__ */ t(n.Close, {
|
|
50
|
+
className: e("inline-flex h-10 cursor-pointer items-center justify-center rounded-full px-3", "text-label-large text-primary transition-colors", "hover:bg-primary/[0.08] focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-primary", "disabled:cursor-not-allowed disabled:opacity-[0.38]", r),
|
|
51
|
+
...i
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
var h = {
|
|
55
|
+
Root: r,
|
|
56
|
+
Trigger: s,
|
|
57
|
+
Portal: i,
|
|
58
|
+
Backdrop: c,
|
|
59
|
+
Viewport: l,
|
|
60
|
+
Popup: u,
|
|
61
|
+
Title: d,
|
|
62
|
+
Description: f,
|
|
63
|
+
Actions: p,
|
|
64
|
+
Close: m,
|
|
65
|
+
Handle: a,
|
|
66
|
+
createHandle: o
|
|
67
|
+
};
|
|
68
|
+
//#endregion
|
|
69
|
+
export { p as Actions, c as Backdrop, m as Close, f as Description, h as Dialog, a as Handle, u as Popup, i as Portal, r as Root, d as Title, s as Trigger, l as Viewport, o as createHandle };
|
|
70
|
+
|
|
71
|
+
//# sourceMappingURL=Dialog.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Dialog.js","names":[],"sources":["../../../src/components/dialog/Dialog.tsx"],"sourcesContent":["import { Dialog as BaseDialog } from '@base-ui/react/dialog'\nimport { cn } from '#/lib/cn'\n\nimport type { ComponentProps } from 'react'\n\n/**\n * Dialog — Material 3 styled wrapper over Base UI's headless Dialog.\n * Behaviour/accessibility (focus trap, role=\"dialog\", dismiss on backdrop\n * click/Esc): Base UI (https://base-ui.com/react/components/dialog).\n * Visuals: M3 dialog anatomy — scrim, extra-large corner, surface-container,\n * headline-small title, body-medium supporting text, text-button actions.\n * Same anatomy as AlertDialog, but dismissible.\n * Design ref: port/core/ui/components/dialogs (see CLAUDE.md).\n *\n * Compound API mirrors Base UI:\n * <Dialog.Root>\n * <Dialog.Trigger>Open</Dialog.Trigger>\n * <Dialog.Portal>\n * <Dialog.Backdrop />\n * <Dialog.Viewport>\n * <Dialog.Popup>\n * <Dialog.Title>Reset settings?</Dialog.Title>\n * <Dialog.Description>This will restore the defaults.</Dialog.Description>\n * <Dialog.Actions>\n * <Dialog.Close>Cancel</Dialog.Close>\n * <Dialog.Close>Reset</Dialog.Close>\n * </Dialog.Actions>\n * </Dialog.Popup>\n * </Dialog.Viewport>\n * </Dialog.Portal>\n * </Dialog.Root>\n */\n\nconst Root = BaseDialog.Root\nconst Portal = BaseDialog.Portal\n/** Imperative handle for detached triggers — re-exported from Base UI. */\nconst Handle = BaseDialog.Handle\nconst createHandle = BaseDialog.createHandle\n\nfunction Trigger({ className, ...props }: ComponentProps<typeof BaseDialog.Trigger>) {\n return <BaseDialog.Trigger className={cn(className)} {...props} />\n}\n\nfunction Backdrop({ className, ...props }: ComponentProps<typeof BaseDialog.Backdrop>) {\n return (\n <BaseDialog.Backdrop\n className={cn(\n 'fixed inset-0 z-40 bg-scrim transition-opacity duration-200 ease-out',\n 'data-[ending-style]:opacity-0 data-[starting-style]:opacity-0',\n className,\n )}\n {...props}\n />\n )\n}\n\nfunction Viewport({ className, ...props }: ComponentProps<typeof BaseDialog.Viewport>) {\n return (\n <BaseDialog.Viewport\n className={cn('fixed inset-0 z-50 flex items-center justify-center p-4', className)}\n {...props}\n />\n )\n}\n\nfunction Popup({ className, ...props }: ComponentProps<typeof BaseDialog.Popup>) {\n return (\n <BaseDialog.Popup\n className={cn(\n 'flex w-full min-w-[280px] max-w-[560px] flex-col gap-4',\n 'rounded-extra-large bg-surface-container p-6 text-on-surface shadow-mm-3',\n 'transition-all duration-200 ease-out focus:outline-none',\n 'data-[starting-style]:scale-95 data-[starting-style]:opacity-0',\n 'data-[ending-style]:scale-95 data-[ending-style]:opacity-0',\n className,\n )}\n {...props}\n />\n )\n}\n\nfunction Title({ className, ...props }: ComponentProps<typeof BaseDialog.Title>) {\n return (\n <BaseDialog.Title\n className={cn('m-0 text-headline-small text-on-surface', className)}\n {...props}\n />\n )\n}\n\nfunction Description({ className, ...props }: ComponentProps<typeof BaseDialog.Description>) {\n return (\n <BaseDialog.Description\n className={cn('m-0 text-body-medium text-on-surface-variant', className)}\n {...props}\n />\n )\n}\n\n/** Trailing actions row (M3: right-aligned text buttons). */\nfunction Actions({ className, ...props }: ComponentProps<'div'>) {\n return <div className={cn('mt-2 flex items-center justify-end gap-2', className)} {...props} />\n}\n\n/** Closes the dialog; styled as an M3 text button — pair inside <Actions>. */\nfunction Close({ className, ...props }: ComponentProps<typeof BaseDialog.Close>) {\n return (\n <BaseDialog.Close\n className={cn(\n 'inline-flex h-10 cursor-pointer items-center justify-center rounded-full px-3',\n 'text-label-large text-primary transition-colors',\n 'hover:bg-primary/[0.08] focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-primary',\n 'disabled:cursor-not-allowed disabled:opacity-[0.38]',\n className,\n )}\n {...props}\n />\n )\n}\n\nexport const Dialog = {\n Root,\n Trigger,\n Portal,\n Backdrop,\n Viewport,\n Popup,\n Title,\n Description,\n Actions,\n Close,\n Handle,\n createHandle,\n}\nexport {\n Root,\n Trigger,\n Portal,\n Backdrop,\n Viewport,\n Popup,\n Title,\n Description,\n Actions,\n Close,\n Handle,\n createHandle,\n}\n"],"mappings":";;;;AAiCA,IAAM,IAAO,EAAW,MAClB,IAAS,EAAW,QAEpB,IAAS,EAAW,QACpB,IAAe,EAAW;AAEhC,SAAS,EAAQ,EAAE,cAAW,GAAG,KAAoD;CACnF,OAAO,kBAAC,EAAW,SAAZ;EAAoB,WAAW,EAAG,CAAS;EAAG,GAAI;CAAQ,CAAA;AACnE;AAEA,SAAS,EAAS,EAAE,cAAW,GAAG,KAAqD;CACrF,OACE,kBAAC,EAAW,UAAZ;EACE,WAAW,EACT,wEACA,iEACA,CACF;EACA,GAAI;CACL,CAAA;AAEL;AAEA,SAAS,EAAS,EAAE,cAAW,GAAG,KAAqD;CACrF,OACE,kBAAC,EAAW,UAAZ;EACE,WAAW,EAAG,2DAA2D,CAAS;EAClF,GAAI;CACL,CAAA;AAEL;AAEA,SAAS,EAAM,EAAE,cAAW,GAAG,KAAkD;CAC/E,OACE,kBAAC,EAAW,OAAZ;EACE,WAAW,EACT,0DACA,4EACA,2DACA,kEACA,8DACA,CACF;EACA,GAAI;CACL,CAAA;AAEL;AAEA,SAAS,EAAM,EAAE,cAAW,GAAG,KAAkD;CAC/E,OACE,kBAAC,EAAW,OAAZ;EACE,WAAW,EAAG,2CAA2C,CAAS;EAClE,GAAI;CACL,CAAA;AAEL;AAEA,SAAS,EAAY,EAAE,cAAW,GAAG,KAAwD;CAC3F,OACE,kBAAC,EAAW,aAAZ;EACE,WAAW,EAAG,gDAAgD,CAAS;EACvE,GAAI;CACL,CAAA;AAEL;AAGA,SAAS,EAAQ,EAAE,cAAW,GAAG,KAAgC;CAC/D,OAAO,kBAAC,OAAD;EAAK,WAAW,EAAG,4CAA4C,CAAS;EAAG,GAAI;CAAQ,CAAA;AAChG;AAGA,SAAS,EAAM,EAAE,cAAW,GAAG,KAAkD;CAC/E,OACE,kBAAC,EAAW,OAAZ;EACE,WAAW,EACT,iFACA,mDACA,gHACA,uDACA,CACF;EACA,GAAI;CACL,CAAA;AAEL;AAEA,IAAa,IAAS;CACpB;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;AACF"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { Dialog, Root, Trigger, Portal, Backdrop, Viewport, Popup, Title, Description, Actions, Close, Handle, createHandle, } from './Dialog';
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import { Actions as e, Backdrop as t, Close as n, Description as r, Dialog as i, Handle as a, Popup as o, Portal as s, Root as c, Title as l, Trigger as u, Viewport as d, createHandle as f } from "./Dialog.js";
|
|
2
|
+
export { e as Actions, t as Backdrop, n as Close, r as Description, i as Dialog, a as Handle, o as Popup, s as Portal, c as Root, l as Title, u as Trigger, d as Viewport, f as createHandle };
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
import { Drawer as BaseDrawer } from '@base-ui/react/drawer';
|
|
2
|
+
import { ComponentProps } from 'react';
|
|
3
|
+
/**
|
|
4
|
+
* Drawer — Material 3 styled wrapper over Base UI's headless Drawer.
|
|
5
|
+
* Behaviour/accessibility (focus trap, scroll lock, swipe-to-dismiss, snap
|
|
6
|
+
* points): Base UI (https://base-ui.com/react/components/drawer).
|
|
7
|
+
* Visuals: M3 sheet anatomy — scrim, drag handle (32×4 on-surface-variant),
|
|
8
|
+
* surface-container panel, extra-large top corner for bottom sheets, large
|
|
9
|
+
* side corner for side sheets / modal navigation drawers, title-large header.
|
|
10
|
+
* Design refs: port/core/ui/components/sheets (BottomSheet, SideSheet) and
|
|
11
|
+
* port/core/ui/components/navigation-drawer (see CLAUDE.md).
|
|
12
|
+
*
|
|
13
|
+
* Compound API mirrors Base UI:
|
|
14
|
+
* <Drawer.Root> // swipeDirection: 'down' (default) | 'left' | 'right' | 'up'
|
|
15
|
+
* <Drawer.Trigger>Open</Drawer.Trigger>
|
|
16
|
+
* <Drawer.Portal>
|
|
17
|
+
* <Drawer.Backdrop />
|
|
18
|
+
* <Drawer.Viewport>
|
|
19
|
+
* <Drawer.Popup side="bottom"> // side: 'bottom' | 'left' | 'right'
|
|
20
|
+
* <Drawer.DragHandle /> // bottom sheets only
|
|
21
|
+
* <Drawer.Content>
|
|
22
|
+
* <Drawer.Title>Title</Drawer.Title>
|
|
23
|
+
* <Drawer.Description>Supporting text</Drawer.Description>
|
|
24
|
+
* <Drawer.Close>Done</Drawer.Close>
|
|
25
|
+
* </Drawer.Content>
|
|
26
|
+
* </Drawer.Popup>
|
|
27
|
+
* </Drawer.Viewport>
|
|
28
|
+
* </Drawer.Portal>
|
|
29
|
+
* </Drawer.Root>
|
|
30
|
+
*
|
|
31
|
+
* App-shell parts (optional): wrap the page in <Drawer.Provider> with
|
|
32
|
+
* <Drawer.IndentBackground /> + <Drawer.Indent> to scale the app behind an
|
|
33
|
+
* open drawer. <Drawer.SwipeArea> opens the drawer from a screen edge.
|
|
34
|
+
*/
|
|
35
|
+
declare const Root: typeof BaseDrawer.Root;
|
|
36
|
+
declare const Portal: BaseDrawer.Portal;
|
|
37
|
+
declare const Provider: typeof BaseDrawer.Provider;
|
|
38
|
+
declare const Handle: typeof BaseDrawer.Handle;
|
|
39
|
+
declare const createHandle: typeof BaseDrawer.createHandle;
|
|
40
|
+
declare function Trigger({ className, ...props }: ComponentProps<typeof BaseDrawer.Trigger>): import("react").JSX.Element;
|
|
41
|
+
declare function Backdrop({ className, ...props }: ComponentProps<typeof BaseDrawer.Backdrop>): import("react").JSX.Element;
|
|
42
|
+
declare function Viewport({ className, ...props }: ComponentProps<typeof BaseDrawer.Viewport>): import("react").JSX.Element;
|
|
43
|
+
/** Where the sheet rests: M3 bottom sheet, or side sheet / modal nav drawer. */
|
|
44
|
+
type DrawerSide = 'bottom' | 'left' | 'right';
|
|
45
|
+
type PopupProps = ComponentProps<typeof BaseDrawer.Popup> & {
|
|
46
|
+
/**
|
|
47
|
+
* Edge the sheet is docked to. Pair with the matching `swipeDirection` on
|
|
48
|
+
* `Drawer.Root` ('down' for bottom, 'left'/'right' for side sheets).
|
|
49
|
+
* @default 'bottom'
|
|
50
|
+
*/
|
|
51
|
+
side?: DrawerSide;
|
|
52
|
+
};
|
|
53
|
+
declare function Popup({ className, side, ...props }: PopupProps): import("react").JSX.Element;
|
|
54
|
+
/** Scrollable body of the sheet. */
|
|
55
|
+
declare function Content({ className, ...props }: ComponentProps<typeof BaseDrawer.Content>): import("react").JSX.Element;
|
|
56
|
+
declare function Title({ className, ...props }: ComponentProps<typeof BaseDrawer.Title>): import("react").JSX.Element;
|
|
57
|
+
declare function Description({ className, ...props }: ComponentProps<typeof BaseDrawer.Description>): import("react").JSX.Element;
|
|
58
|
+
/** Closes the drawer; styled as an M3 text button. */
|
|
59
|
+
declare function Close({ className, ...props }: ComponentProps<typeof BaseDrawer.Close>): import("react").JSX.Element;
|
|
60
|
+
/**
|
|
61
|
+
* M3 drag handle (32×4, on-surface-variant @ 40%) shown at the top of a
|
|
62
|
+
* bottom sheet to signal swipeability. Not a Base UI part — plain `<div>`.
|
|
63
|
+
*/
|
|
64
|
+
declare function DragHandle({ className, ...props }: ComponentProps<'div'>): import("react").JSX.Element;
|
|
65
|
+
/** Invisible screen-edge area that opens the drawer on swipe. */
|
|
66
|
+
declare function SwipeArea({ className, ...props }: ComponentProps<typeof BaseDrawer.SwipeArea>): import("react").JSX.Element;
|
|
67
|
+
/**
|
|
68
|
+
* Wraps the app's main UI inside `<Drawer.Provider>`; gets `data-active`
|
|
69
|
+
* while any drawer is open, scaling the page back behind the sheet.
|
|
70
|
+
*/
|
|
71
|
+
declare function Indent({ className, ...props }: ComponentProps<typeof BaseDrawer.Indent>): import("react").JSX.Element;
|
|
72
|
+
/** Background layer revealed behind a scaled `<Drawer.Indent>`. */
|
|
73
|
+
declare function IndentBackground({ className, ...props }: ComponentProps<typeof BaseDrawer.IndentBackground>): import("react").JSX.Element;
|
|
74
|
+
export declare const Drawer: {
|
|
75
|
+
Root: typeof BaseDrawer.Root;
|
|
76
|
+
Trigger: typeof Trigger;
|
|
77
|
+
Portal: BaseDrawer.Portal;
|
|
78
|
+
Backdrop: typeof Backdrop;
|
|
79
|
+
Viewport: typeof Viewport;
|
|
80
|
+
Popup: typeof Popup;
|
|
81
|
+
Content: typeof Content;
|
|
82
|
+
Title: typeof Title;
|
|
83
|
+
Description: typeof Description;
|
|
84
|
+
Close: typeof Close;
|
|
85
|
+
DragHandle: typeof DragHandle;
|
|
86
|
+
SwipeArea: typeof SwipeArea;
|
|
87
|
+
Provider: typeof BaseDrawer.Provider;
|
|
88
|
+
Indent: typeof Indent;
|
|
89
|
+
IndentBackground: typeof IndentBackground;
|
|
90
|
+
Handle: typeof BaseDrawer.Handle;
|
|
91
|
+
createHandle: typeof BaseDrawer.createHandle;
|
|
92
|
+
};
|
|
93
|
+
export { Root, Trigger, Portal, Backdrop, Viewport, Popup, Content, Title, Description, Close, DragHandle, SwipeArea, Provider, Indent, IndentBackground, Handle, createHandle, };
|