@open-mercato/ui 0.6.1-develop.3256.1.fe3dec2464 → 0.6.1-develop.3260.1.dc719cac84
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/.turbo/turbo-build.log +1 -1
- package/dist/backend/CrudForm.js +46 -129
- package/dist/backend/CrudForm.js.map +3 -3
- package/dist/backend/DataTable.js +10 -3
- package/dist/backend/DataTable.js.map +2 -2
- package/dist/backend/EmptyState.js +1 -47
- package/dist/backend/EmptyState.js.map +2 -2
- package/dist/backend/FilterOverlay.js +31 -26
- package/dist/backend/FilterOverlay.js.map +2 -2
- package/dist/backend/FlashMessages.js +23 -25
- package/dist/backend/FlashMessages.js.map +2 -2
- package/dist/backend/JsonBuilder.js +4 -2
- package/dist/backend/JsonBuilder.js.map +2 -2
- package/dist/backend/LogList.js +49 -0
- package/dist/backend/LogList.js.map +7 -0
- package/dist/backend/crud/CollapsibleGroup.js +13 -3
- package/dist/backend/crud/CollapsibleGroup.js.map +2 -2
- package/dist/backend/detail/InlineEditors.js +80 -32
- package/dist/backend/detail/InlineEditors.js.map +2 -2
- package/dist/backend/inputs/ComboboxInput.js +60 -6
- package/dist/backend/inputs/ComboboxInput.js.map +2 -2
- package/dist/backend/inputs/DatePicker.js +6 -142
- package/dist/backend/inputs/DatePicker.js.map +2 -2
- package/dist/backend/inputs/DateTimePicker.js +6 -182
- package/dist/backend/inputs/DateTimePicker.js.map +2 -2
- package/dist/backend/inputs/TagsInput.js +16 -19
- package/dist/backend/inputs/TagsInput.js.map +2 -2
- package/dist/backend/inputs/TimeInput.js +1 -1
- package/dist/backend/inputs/TimeInput.js.map +2 -2
- package/dist/backend/inputs/TimePicker.js +83 -72
- package/dist/backend/inputs/TimePicker.js.map +2 -2
- package/dist/backend/utils/customFieldForms.js +2 -2
- package/dist/backend/utils/customFieldForms.js.map +1 -1
- package/dist/portal/components/PortalEmptyState.js +13 -9
- package/dist/portal/components/PortalEmptyState.js.map +2 -2
- package/dist/primitives/accordion.js +137 -0
- package/dist/primitives/accordion.js.map +7 -0
- package/dist/primitives/alert.js +180 -12
- package/dist/primitives/alert.js.map +2 -2
- package/dist/primitives/calendar.js +122 -32
- package/dist/primitives/calendar.js.map +2 -2
- package/dist/primitives/compact-select.js +47 -0
- package/dist/primitives/compact-select.js.map +7 -0
- package/dist/primitives/counter-input.js +174 -0
- package/dist/primitives/counter-input.js.map +7 -0
- package/dist/primitives/date-picker-helpers.js +79 -0
- package/dist/primitives/date-picker-helpers.js.map +7 -0
- package/dist/primitives/date-picker.js +216 -0
- package/dist/primitives/date-picker.js.map +7 -0
- package/dist/primitives/date-range-picker.js +239 -0
- package/dist/primitives/date-range-picker.js.map +7 -0
- package/dist/primitives/digit-input.js +157 -0
- package/dist/primitives/digit-input.js.map +7 -0
- package/dist/primitives/empty-state.js +93 -0
- package/dist/primitives/empty-state.js.map +7 -0
- package/dist/primitives/inline-input.js +29 -0
- package/dist/primitives/inline-input.js.map +7 -0
- package/dist/primitives/inline-select.js +41 -0
- package/dist/primitives/inline-select.js.map +7 -0
- package/dist/primitives/notification-stack.js +116 -0
- package/dist/primitives/notification-stack.js.map +7 -0
- package/dist/primitives/notification.js +62 -0
- package/dist/primitives/notification.js.map +7 -0
- package/dist/primitives/rich-editor.js +1230 -0
- package/dist/primitives/rich-editor.js.map +7 -0
- package/dist/primitives/select.js +1 -0
- package/dist/primitives/select.js.map +2 -2
- package/dist/primitives/skeleton.js +55 -0
- package/dist/primitives/skeleton.js.map +7 -0
- package/dist/primitives/tag-input.js +186 -0
- package/dist/primitives/tag-input.js.map +7 -0
- package/dist/primitives/tag.js +66 -13
- package/dist/primitives/tag.js.map +2 -2
- package/dist/primitives/time-picker.js +793 -0
- package/dist/primitives/time-picker.js.map +7 -0
- package/package.json +4 -3
- package/src/backend/CrudForm.tsx +61 -113
- package/src/backend/DataTable.tsx +17 -5
- package/src/backend/EmptyState.tsx +13 -63
- package/src/backend/FilterOverlay.tsx +38 -22
- package/src/backend/FlashMessages.tsx +23 -24
- package/src/backend/JsonBuilder.tsx +4 -2
- package/src/backend/LogList.tsx +109 -0
- package/src/backend/__tests__/CrudForm.datetime.test.tsx +12 -7
- package/src/backend/__tests__/FilterOverlay.dateRange.test.tsx +89 -0
- package/src/backend/__tests__/LogList.test.tsx +163 -0
- package/src/backend/crud/CollapsibleGroup.tsx +17 -3
- package/src/backend/detail/InlineEditors.tsx +78 -25
- package/src/backend/detail/__tests__/InlineEditors.test.tsx +81 -1
- package/src/backend/inputs/ComboboxInput.tsx +81 -9
- package/src/backend/inputs/DatePicker.tsx +28 -155
- package/src/backend/inputs/DateTimePicker.tsx +25 -193
- package/src/backend/inputs/TagsInput.tsx +10 -13
- package/src/backend/inputs/TimeInput.tsx +2 -1
- package/src/backend/inputs/TimePicker.tsx +99 -70
- package/src/backend/inputs/__tests__/ComboboxInput.test.tsx +133 -0
- package/src/backend/inputs/__tests__/TimePicker.test.tsx +2 -2
- package/src/backend/utils/__tests__/richTextSanitizer.test.ts +5 -2
- package/src/backend/utils/customFieldForms.ts +2 -2
- package/src/portal/components/PortalEmptyState.tsx +27 -22
- package/src/primitives/__tests__/accordion.test.tsx +197 -0
- package/src/primitives/__tests__/alert.test.tsx +204 -0
- package/src/primitives/__tests__/compact-select.test.tsx +98 -0
- package/src/primitives/__tests__/counter-input.test.tsx +165 -0
- package/src/primitives/__tests__/date-picker.test.tsx +221 -0
- package/src/primitives/__tests__/date-range-picker.test.tsx +173 -0
- package/src/primitives/__tests__/digit-input.test.tsx +168 -0
- package/src/primitives/__tests__/empty-state.test.tsx +154 -0
- package/src/primitives/__tests__/inline-input.test.tsx +100 -0
- package/src/primitives/__tests__/inline-select.test.tsx +103 -0
- package/src/primitives/__tests__/notification-stack.test.tsx +174 -0
- package/src/primitives/__tests__/notification.test.tsx +119 -0
- package/src/primitives/__tests__/rich-editor.test.tsx +411 -0
- package/src/primitives/__tests__/skeleton.test.tsx +76 -0
- package/src/primitives/__tests__/tag-input.test.tsx +198 -0
- package/src/primitives/__tests__/tag.test.tsx +123 -0
- package/src/primitives/__tests__/time-picker.test.tsx +392 -0
- package/src/primitives/accordion.tsx +225 -0
- package/src/primitives/alert.tsx +234 -24
- package/src/primitives/calendar.tsx +146 -38
- package/src/primitives/compact-select.tsx +59 -0
- package/src/primitives/counter-input.tsx +211 -0
- package/src/primitives/date-picker-helpers.ts +96 -0
- package/src/primitives/date-picker.tsx +290 -0
- package/src/primitives/date-range-picker.tsx +281 -0
- package/src/primitives/digit-input.tsx +208 -0
- package/src/primitives/empty-state.tsx +140 -0
- package/src/primitives/inline-input.tsx +55 -0
- package/src/primitives/inline-select.tsx +74 -0
- package/src/primitives/notification-stack.tsx +185 -0
- package/src/primitives/notification.tsx +136 -0
- package/src/primitives/rich-editor.tsx +1578 -0
- package/src/primitives/select.tsx +1 -0
- package/src/primitives/skeleton.tsx +70 -0
- package/src/primitives/tag-input.tsx +223 -0
- package/src/primitives/tag.tsx +69 -10
- package/src/primitives/time-picker.tsx +1059 -0
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/primitives/calendar.tsx"],
|
|
4
|
-
"sourcesContent": ["\"use client\"\n\nimport * as React from 'react'\nimport { DayPicker } from 'react-day-picker'\nimport type { DayPickerProps } from 'react-day-picker'\nimport { ChevronLeft, ChevronRight } from 'lucide-react'\nimport { cn } from '@open-mercato/shared/lib/utils'\n\nexport type CalendarProps = DayPickerProps\n\
|
|
5
|
-
"mappings": ";
|
|
4
|
+
"sourcesContent": ["\"use client\"\n\nimport * as React from 'react'\nimport { DayPicker, useDayPicker } from 'react-day-picker'\nimport type { DayPickerProps, CalendarMonth } from 'react-day-picker'\nimport { ChevronLeft, ChevronRight } from 'lucide-react'\nimport { format } from 'date-fns'\nimport type { Locale } from 'date-fns'\nimport { cn } from '@open-mercato/shared/lib/utils'\n\nexport type CalendarProps = DayPickerProps\n\nfunction MonthNavButton({\n direction,\n locale,\n}: {\n direction: 'prev' | 'next'\n locale?: Locale\n}) {\n const dayPicker = useDayPicker() as unknown as {\n previousMonth?: Date\n nextMonth?: Date\n goToMonth?: (month: Date) => void\n }\n const target = direction === 'prev' ? dayPicker.previousMonth : dayPicker.nextMonth\n const Icon = direction === 'prev' ? ChevronLeft : ChevronRight\n const targetLabel = format(target ?? new Date(), 'MMMM yyyy', locale ? { locale } : undefined)\n const ariaLabel = `Go to ${direction === 'prev' ? 'previous' : 'next'} month: ${targetLabel}`\n return (\n <button\n type=\"button\"\n disabled={!target}\n aria-label={ariaLabel}\n onClick={() => {\n if (target && dayPicker.goToMonth) dayPicker.goToMonth(target)\n }}\n className={cn(\n 'h-9 w-9 inline-flex items-center justify-center rounded-md shrink-0',\n 'border border-border bg-background text-muted-foreground transition-colors',\n 'hover:bg-accent hover:text-accent-foreground hover:border-input',\n 'focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2',\n 'disabled:opacity-30 disabled:pointer-events-none disabled:hover:bg-background',\n )}\n >\n <Icon className=\"h-4 w-4\" aria-hidden=\"true\" />\n </button>\n )\n}\n\nfunction buildMonthCaption(locale: Locale | undefined, totalMonths: number) {\n return function MonthCaption({\n calendarMonth,\n displayIndex,\n }: {\n calendarMonth: CalendarMonth\n displayIndex?: number\n }) {\n const label = format(calendarMonth.date, 'MMMM yyyy', locale ? { locale } : undefined)\n const index = typeof displayIndex === 'number' ? displayIndex : 0\n // For multi-month layouts (e.g. range pickers) only the leftmost month\n // exposes the previous-month chevron and only the rightmost exposes the\n // next-month chevron. Navigation is always global across all visible\n // months, so showing both arrows on every month is confusing.\n const showPrev = index === 0\n const showNext = index === totalMonths - 1\n return (\n <div className=\"flex items-center justify-between gap-2 mb-3\">\n {showPrev ? (\n <MonthNavButton direction=\"prev\" locale={locale} />\n ) : (\n <div className=\"h-9 w-9 shrink-0\" aria-hidden=\"true\" />\n )}\n <div\n className=\"flex-1 flex items-center justify-center h-9 rounded-md bg-muted px-3 text-sm font-medium\"\n aria-live=\"polite\"\n >\n {label}\n </div>\n {showNext ? (\n <MonthNavButton direction=\"next\" locale={locale} />\n ) : (\n <div className=\"h-9 w-9 shrink-0\" aria-hidden=\"true\" />\n )}\n </div>\n )\n }\n}\n\nexport function Calendar({\n className,\n classNames,\n showOutsideDays = true,\n fixedWeeks = true,\n locale,\n components,\n numberOfMonths = 1,\n pagedNavigation = true,\n ...props\n}: CalendarProps) {\n const monthCaption = React.useMemo(\n () => buildMonthCaption(locale as Locale | undefined, numberOfMonths),\n [locale, numberOfMonths],\n )\n return (\n <DayPicker\n showOutsideDays={showOutsideDays}\n fixedWeeks={fixedWeeks}\n pagedNavigation={pagedNavigation}\n locale={locale}\n numberOfMonths={numberOfMonths}\n className={cn('p-3', className)}\n classNames={{\n months: 'flex flex-col sm:flex-row gap-4',\n month: 'space-y-2',\n month_caption: '',\n caption_label: 'sr-only',\n nav: 'sr-only',\n month_grid: 'w-full border-collapse',\n weekdays: 'flex',\n weekday: 'text-muted-foreground rounded-md w-9 font-normal text-xs',\n weeks: 'w-full border-collapse',\n week: 'flex w-full mt-1',\n day: 'h-9 w-9 text-center text-sm p-0 relative focus-within:relative focus-within:z-20',\n day_button: cn(\n 'h-9 w-9 p-0 font-normal aria-selected:opacity-100',\n 'inline-flex items-center justify-center rounded-md text-sm',\n 'transition-colors focus:outline-none focus-visible:outline-none disabled:pointer-events-none',\n // Focus indicator is a soft accent fill instead of a ring overlay \u2014 keyboard\n // users get a visible cue, but mouse-click focus does not leave a stuck ring\n // on top of the selected cell.\n 'hover:bg-accent hover:text-accent-foreground',\n 'focus-visible:bg-accent focus-visible:text-accent-foreground',\n ),\n // React-day-picker v9 applies `classNames.selected` / `range_*` to the day\n // CELL (`<td>`) wrapper, not to the inner `<button>`. To keep the parent\n // fill visible through interaction, we (a) paint the cell with the desired\n // bg/text, and (b) force the inner button to render transparent \u2014 so the\n // button's own hover/focus-visible bg overrides cannot cover the cell fill.\n selected: cn(\n '!bg-primary !text-primary-foreground rounded-md',\n '[&_button]:!bg-transparent [&_button]:!text-primary-foreground',\n '[&_button:hover]:!bg-transparent [&_button:hover]:!text-primary-foreground',\n '[&_button:focus-visible]:!bg-transparent [&_button:focus-visible]:!text-primary-foreground',\n ),\n range_start: cn(\n '!bg-primary !text-primary-foreground rounded-l-md !rounded-r-none',\n '[&_button]:!bg-transparent [&_button]:!text-primary-foreground',\n '[&_button:hover]:!bg-transparent [&_button:hover]:!text-primary-foreground',\n '[&_button:focus-visible]:!bg-transparent [&_button:focus-visible]:!text-primary-foreground',\n ),\n range_end: cn(\n '!bg-primary !text-primary-foreground rounded-r-md !rounded-l-none',\n '[&_button]:!bg-transparent [&_button]:!text-primary-foreground',\n '[&_button:hover]:!bg-transparent [&_button:hover]:!text-primary-foreground',\n '[&_button:focus-visible]:!bg-transparent [&_button:focus-visible]:!text-primary-foreground',\n ),\n range_middle: cn(\n '!bg-accent !text-accent-foreground !rounded-none',\n '[&_button]:!bg-transparent [&_button]:!text-accent-foreground',\n '[&_button:hover]:!bg-transparent [&_button:hover]:!text-accent-foreground',\n '[&_button:focus-visible]:!bg-transparent [&_button:focus-visible]:!text-accent-foreground',\n ),\n today: 'font-semibold text-primary rounded-md',\n outside:\n 'day-outside text-muted-foreground opacity-40 aria-selected:bg-accent/50 aria-selected:text-muted-foreground aria-selected:opacity-30',\n disabled: 'text-muted-foreground opacity-50',\n hidden: 'invisible',\n ...classNames,\n }}\n components={{\n MonthCaption: monthCaption,\n ...components,\n }}\n {...props}\n />\n )\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
3
|
+
import * as React from "react";
|
|
4
|
+
import { cn } from "@open-mercato/shared/lib/utils";
|
|
5
|
+
import {
|
|
6
|
+
Select,
|
|
7
|
+
SelectContent,
|
|
8
|
+
SelectGroup,
|
|
9
|
+
SelectItem,
|
|
10
|
+
SelectLabel,
|
|
11
|
+
SelectSeparator,
|
|
12
|
+
SelectTrigger,
|
|
13
|
+
SelectValue
|
|
14
|
+
} from "./select.js";
|
|
15
|
+
const CompactSelectTrigger = React.forwardRef(({ triggerLabel, children, className, ...props }, ref) => /* @__PURE__ */ jsxs(
|
|
16
|
+
SelectTrigger,
|
|
17
|
+
{
|
|
18
|
+
ref,
|
|
19
|
+
size: "xs",
|
|
20
|
+
className: cn(className),
|
|
21
|
+
"data-slot": "compact-select-trigger",
|
|
22
|
+
...props,
|
|
23
|
+
children: [
|
|
24
|
+
triggerLabel ? /* @__PURE__ */ jsx(
|
|
25
|
+
"span",
|
|
26
|
+
{
|
|
27
|
+
className: "shrink-0 text-xs font-medium text-muted-foreground",
|
|
28
|
+
"data-slot": "compact-select-trigger-label",
|
|
29
|
+
children: triggerLabel
|
|
30
|
+
}
|
|
31
|
+
) : null,
|
|
32
|
+
children
|
|
33
|
+
]
|
|
34
|
+
}
|
|
35
|
+
));
|
|
36
|
+
CompactSelectTrigger.displayName = "CompactSelectTrigger";
|
|
37
|
+
export {
|
|
38
|
+
CompactSelectTrigger,
|
|
39
|
+
Select,
|
|
40
|
+
SelectContent,
|
|
41
|
+
SelectGroup,
|
|
42
|
+
SelectItem,
|
|
43
|
+
SelectLabel,
|
|
44
|
+
SelectSeparator,
|
|
45
|
+
SelectValue
|
|
46
|
+
};
|
|
47
|
+
//# sourceMappingURL=compact-select.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../src/primitives/compact-select.tsx"],
|
|
4
|
+
"sourcesContent": ["\"use client\"\n\nimport * as React from 'react'\nimport { cn } from '@open-mercato/shared/lib/utils'\nimport {\n Select,\n SelectContent,\n SelectGroup,\n SelectItem,\n SelectLabel,\n SelectSeparator,\n SelectTrigger,\n SelectValue,\n type SelectTriggerProps,\n} from './select'\n\nexport type CompactSelectTriggerProps = Omit<SelectTriggerProps, 'size'> & {\n /**\n * Optional inline prefix rendered before the selected value, e.g. `View:` or\n * `Sort by:`. Renders in muted style and shrinks before the value text.\n */\n triggerLabel?: React.ReactNode\n}\n\nexport const CompactSelectTrigger = React.forwardRef<\n React.ElementRef<typeof SelectTrigger>,\n CompactSelectTriggerProps\n>(({ triggerLabel, children, className, ...props }, ref) => (\n <SelectTrigger\n ref={ref}\n size=\"xs\"\n className={cn(className)}\n data-slot=\"compact-select-trigger\"\n {...props}\n >\n {triggerLabel ? (\n <span\n className=\"shrink-0 text-xs font-medium text-muted-foreground\"\n data-slot=\"compact-select-trigger-label\"\n >\n {triggerLabel}\n </span>\n ) : null}\n {children}\n </SelectTrigger>\n))\nCompactSelectTrigger.displayName = 'CompactSelectTrigger'\n\n// Re-export the rest of the Select API so consumers can import the entire\n// compact-select composition from one path.\nexport {\n Select,\n SelectContent,\n SelectGroup,\n SelectItem,\n SelectLabel,\n SelectSeparator,\n SelectValue,\n}\n"],
|
|
5
|
+
"mappings": ";AA4BE,SAQI,KARJ;AA1BF,YAAY,WAAW;AACvB,SAAS,UAAU;AACnB;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OAEK;AAUA,MAAM,uBAAuB,MAAM,WAGxC,CAAC,EAAE,cAAc,UAAU,WAAW,GAAG,MAAM,GAAG,QAClD;AAAA,EAAC;AAAA;AAAA,IACC;AAAA,IACA,MAAK;AAAA,IACL,WAAW,GAAG,SAAS;AAAA,IACvB,aAAU;AAAA,IACT,GAAG;AAAA,IAEH;AAAA,qBACC;AAAA,QAAC;AAAA;AAAA,UACC,WAAU;AAAA,UACV,aAAU;AAAA,UAET;AAAA;AAAA,MACH,IACE;AAAA,MACH;AAAA;AAAA;AACH,CACD;AACD,qBAAqB,cAAc;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
3
|
+
import * as React from "react";
|
|
4
|
+
import { Minus, Plus } from "lucide-react";
|
|
5
|
+
import { cva } from "class-variance-authority";
|
|
6
|
+
import { cn } from "@open-mercato/shared/lib/utils";
|
|
7
|
+
const counterWrapperVariants = cva(
|
|
8
|
+
"inline-flex w-full items-center bg-background border border-input shadow-xs transition-colors focus-within:outline-none focus-within:shadow-focus focus-within:border-foreground hover:bg-muted/40 has-[input:disabled]:bg-bg-disabled has-[input:disabled]:border-border-disabled has-[input:disabled]:shadow-none has-[input:disabled]:hover:bg-bg-disabled has-[input[aria-invalid=true]]:border-destructive has-[input[aria-invalid=true]]:focus-within:border-destructive",
|
|
9
|
+
{
|
|
10
|
+
variants: {
|
|
11
|
+
size: {
|
|
12
|
+
sm: "h-8 gap-1 p-1 rounded-md",
|
|
13
|
+
default: "h-9 gap-1.5 p-1.5 rounded-md",
|
|
14
|
+
lg: "h-10 gap-2 p-2 rounded-[10px]"
|
|
15
|
+
}
|
|
16
|
+
},
|
|
17
|
+
defaultVariants: { size: "default" }
|
|
18
|
+
}
|
|
19
|
+
);
|
|
20
|
+
const counterButtonVariants = cva(
|
|
21
|
+
"inline-flex shrink-0 items-center justify-center rounded-md text-muted-foreground transition-colors hover:bg-muted hover:text-foreground focus:outline-none focus-visible:ring-2 focus-visible:ring-ring/40 disabled:pointer-events-none disabled:opacity-50",
|
|
22
|
+
{
|
|
23
|
+
variants: {
|
|
24
|
+
size: {
|
|
25
|
+
sm: "size-6 [&_svg]:size-3.5",
|
|
26
|
+
default: "size-6 [&_svg]:size-4",
|
|
27
|
+
lg: "size-6 [&_svg]:size-4"
|
|
28
|
+
}
|
|
29
|
+
},
|
|
30
|
+
defaultVariants: { size: "default" }
|
|
31
|
+
}
|
|
32
|
+
);
|
|
33
|
+
const counterInputElementVariants = cva(
|
|
34
|
+
"flex-1 min-w-0 bg-transparent border-0 outline-none text-center placeholder:text-muted-foreground disabled:cursor-not-allowed disabled:bg-transparent [appearance:textfield] [&::-webkit-outer-spin-button]:appearance-none [&::-webkit-inner-spin-button]:appearance-none",
|
|
35
|
+
{
|
|
36
|
+
variants: {
|
|
37
|
+
size: {
|
|
38
|
+
sm: "text-xs",
|
|
39
|
+
default: "text-sm",
|
|
40
|
+
lg: "text-sm"
|
|
41
|
+
}
|
|
42
|
+
},
|
|
43
|
+
defaultVariants: { size: "default" }
|
|
44
|
+
}
|
|
45
|
+
);
|
|
46
|
+
const CounterInput = React.forwardRef(
|
|
47
|
+
({
|
|
48
|
+
className,
|
|
49
|
+
inputClassName,
|
|
50
|
+
size,
|
|
51
|
+
value: valueProp,
|
|
52
|
+
onChange,
|
|
53
|
+
min,
|
|
54
|
+
max,
|
|
55
|
+
step = 1,
|
|
56
|
+
precision = 0,
|
|
57
|
+
disabled = false,
|
|
58
|
+
placeholder,
|
|
59
|
+
decrementAriaLabel = "Decrease",
|
|
60
|
+
incrementAriaLabel = "Increase",
|
|
61
|
+
...rest
|
|
62
|
+
}, ref) => {
|
|
63
|
+
const [internalValue, setInternalValue] = React.useState(
|
|
64
|
+
valueProp ?? null
|
|
65
|
+
);
|
|
66
|
+
const isControlled = valueProp !== void 0;
|
|
67
|
+
const value = isControlled ? valueProp ?? null : internalValue;
|
|
68
|
+
const factor = React.useMemo(() => 10 ** precision, [precision]);
|
|
69
|
+
const clamp = React.useCallback(
|
|
70
|
+
(n) => {
|
|
71
|
+
let next = n;
|
|
72
|
+
if (typeof min === "number" && next < min) next = min;
|
|
73
|
+
if (typeof max === "number" && next > max) next = max;
|
|
74
|
+
return Math.round(next * factor) / factor;
|
|
75
|
+
},
|
|
76
|
+
[factor, max, min]
|
|
77
|
+
);
|
|
78
|
+
const commitValue = React.useCallback(
|
|
79
|
+
(next) => {
|
|
80
|
+
if (!isControlled) setInternalValue(next);
|
|
81
|
+
onChange?.(next);
|
|
82
|
+
},
|
|
83
|
+
[isControlled, onChange]
|
|
84
|
+
);
|
|
85
|
+
const formatNumber = React.useCallback(
|
|
86
|
+
(n) => precision > 0 ? n.toFixed(precision) : String(n),
|
|
87
|
+
[precision]
|
|
88
|
+
);
|
|
89
|
+
const adjust = React.useCallback(
|
|
90
|
+
(direction) => {
|
|
91
|
+
const current = typeof value === "number" ? value : 0;
|
|
92
|
+
commitValue(clamp(current + direction * step));
|
|
93
|
+
},
|
|
94
|
+
[clamp, commitValue, step, value]
|
|
95
|
+
);
|
|
96
|
+
const handleInputChange = (event) => {
|
|
97
|
+
const text = event.target.value;
|
|
98
|
+
if (text === "" || text === "-") {
|
|
99
|
+
commitValue(null);
|
|
100
|
+
return;
|
|
101
|
+
}
|
|
102
|
+
const parsed = Number(text);
|
|
103
|
+
if (!Number.isFinite(parsed)) return;
|
|
104
|
+
commitValue(clamp(parsed));
|
|
105
|
+
};
|
|
106
|
+
const handleKeyDown = (event) => {
|
|
107
|
+
if (event.key === "ArrowUp") {
|
|
108
|
+
event.preventDefault();
|
|
109
|
+
adjust(1);
|
|
110
|
+
} else if (event.key === "ArrowDown") {
|
|
111
|
+
event.preventDefault();
|
|
112
|
+
adjust(-1);
|
|
113
|
+
}
|
|
114
|
+
};
|
|
115
|
+
const incrementDisabled = disabled || typeof max === "number" && value !== null && value >= max;
|
|
116
|
+
const decrementDisabled = disabled || typeof min === "number" && value !== null && value <= min;
|
|
117
|
+
return /* @__PURE__ */ jsxs(
|
|
118
|
+
"div",
|
|
119
|
+
{
|
|
120
|
+
className: cn(counterWrapperVariants({ size }), className),
|
|
121
|
+
"data-slot": "counter-input",
|
|
122
|
+
children: [
|
|
123
|
+
/* @__PURE__ */ jsx(
|
|
124
|
+
"button",
|
|
125
|
+
{
|
|
126
|
+
type: "button",
|
|
127
|
+
onClick: () => adjust(-1),
|
|
128
|
+
disabled: decrementDisabled,
|
|
129
|
+
"aria-label": decrementAriaLabel,
|
|
130
|
+
className: cn(counterButtonVariants({ size })),
|
|
131
|
+
"data-slot": "counter-input-decrement",
|
|
132
|
+
children: /* @__PURE__ */ jsx(Minus, { "aria-hidden": "true" })
|
|
133
|
+
}
|
|
134
|
+
),
|
|
135
|
+
/* @__PURE__ */ jsx(
|
|
136
|
+
"input",
|
|
137
|
+
{
|
|
138
|
+
ref,
|
|
139
|
+
type: "number",
|
|
140
|
+
inputMode: "decimal",
|
|
141
|
+
value: value === null ? "" : formatNumber(value),
|
|
142
|
+
onChange: handleInputChange,
|
|
143
|
+
onKeyDown: handleKeyDown,
|
|
144
|
+
disabled,
|
|
145
|
+
placeholder,
|
|
146
|
+
min,
|
|
147
|
+
max,
|
|
148
|
+
step,
|
|
149
|
+
className: cn(counterInputElementVariants({ size }), inputClassName),
|
|
150
|
+
...rest
|
|
151
|
+
}
|
|
152
|
+
),
|
|
153
|
+
/* @__PURE__ */ jsx(
|
|
154
|
+
"button",
|
|
155
|
+
{
|
|
156
|
+
type: "button",
|
|
157
|
+
onClick: () => adjust(1),
|
|
158
|
+
disabled: incrementDisabled,
|
|
159
|
+
"aria-label": incrementAriaLabel,
|
|
160
|
+
className: cn(counterButtonVariants({ size })),
|
|
161
|
+
"data-slot": "counter-input-increment",
|
|
162
|
+
children: /* @__PURE__ */ jsx(Plus, { "aria-hidden": "true" })
|
|
163
|
+
}
|
|
164
|
+
)
|
|
165
|
+
]
|
|
166
|
+
}
|
|
167
|
+
);
|
|
168
|
+
}
|
|
169
|
+
);
|
|
170
|
+
CounterInput.displayName = "CounterInput";
|
|
171
|
+
export {
|
|
172
|
+
CounterInput
|
|
173
|
+
};
|
|
174
|
+
//# sourceMappingURL=counter-input.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../src/primitives/counter-input.tsx"],
|
|
4
|
+
"sourcesContent": ["\"use client\"\n\nimport * as React from 'react'\nimport { Minus, Plus } from 'lucide-react'\nimport { cva, type VariantProps } from 'class-variance-authority'\nimport { cn } from '@open-mercato/shared/lib/utils'\n\nconst counterWrapperVariants = cva(\n 'inline-flex w-full items-center bg-background border border-input shadow-xs transition-colors ' +\n 'focus-within:outline-none focus-within:shadow-focus focus-within:border-foreground ' +\n 'hover:bg-muted/40 ' +\n 'has-[input:disabled]:bg-bg-disabled has-[input:disabled]:border-border-disabled has-[input:disabled]:shadow-none has-[input:disabled]:hover:bg-bg-disabled ' +\n 'has-[input[aria-invalid=true]]:border-destructive has-[input[aria-invalid=true]]:focus-within:border-destructive',\n {\n variants: {\n size: {\n sm: 'h-8 gap-1 p-1 rounded-md',\n default: 'h-9 gap-1.5 p-1.5 rounded-md',\n lg: 'h-10 gap-2 p-2 rounded-[10px]',\n },\n },\n defaultVariants: { size: 'default' },\n },\n)\n\nconst counterButtonVariants = cva(\n 'inline-flex shrink-0 items-center justify-center rounded-md text-muted-foreground transition-colors hover:bg-muted hover:text-foreground focus:outline-none focus-visible:ring-2 focus-visible:ring-ring/40 disabled:pointer-events-none disabled:opacity-50',\n {\n variants: {\n size: {\n sm: 'size-6 [&_svg]:size-3.5',\n default: 'size-6 [&_svg]:size-4',\n lg: 'size-6 [&_svg]:size-4',\n },\n },\n defaultVariants: { size: 'default' },\n },\n)\n\nconst counterInputElementVariants = cva(\n 'flex-1 min-w-0 bg-transparent border-0 outline-none text-center placeholder:text-muted-foreground disabled:cursor-not-allowed disabled:bg-transparent ' +\n '[appearance:textfield] [&::-webkit-outer-spin-button]:appearance-none [&::-webkit-inner-spin-button]:appearance-none',\n {\n variants: {\n size: {\n sm: 'text-xs',\n default: 'text-sm',\n lg: 'text-sm',\n },\n },\n defaultVariants: { size: 'default' },\n },\n)\n\nexport type CounterInputProps = Omit<\n React.ComponentPropsWithoutRef<'input'>,\n 'value' | 'onChange' | 'size' | 'type' | 'children'\n> &\n VariantProps<typeof counterWrapperVariants> & {\n value?: number | null\n /**\n * Fired whenever the value changes through `-`/`+`, keyboard arrows, or direct typing.\n * `null` is emitted when the user clears the input. Component clamps to `min`/`max`\n * and rounds to `precision` decimal places before emitting.\n */\n onChange?: (value: number | null) => void\n min?: number\n max?: number\n /** Increment amount for `+` / `-` and ArrowUp / ArrowDown. Default `1`. */\n step?: number\n /** Decimal places used when formatting the displayed value. Default `0`. */\n precision?: number\n /** aria-label for the decrement (`-`) button. Default English `Decrease`. */\n decrementAriaLabel?: string\n /** aria-label for the increment (`+`) button. Default English `Increase`. */\n incrementAriaLabel?: string\n /** Override classes applied to the inner `<input>` element. */\n inputClassName?: string\n }\n\nexport const CounterInput = React.forwardRef<HTMLInputElement, CounterInputProps>(\n (\n {\n className,\n inputClassName,\n size,\n value: valueProp,\n onChange,\n min,\n max,\n step = 1,\n precision = 0,\n disabled = false,\n placeholder,\n decrementAriaLabel = 'Decrease',\n incrementAriaLabel = 'Increase',\n ...rest\n },\n ref,\n ) => {\n const [internalValue, setInternalValue] = React.useState<number | null>(\n valueProp ?? null,\n )\n const isControlled = valueProp !== undefined\n const value = isControlled ? valueProp ?? null : internalValue\n\n const factor = React.useMemo(() => 10 ** precision, [precision])\n\n const clamp = React.useCallback(\n (n: number) => {\n let next = n\n if (typeof min === 'number' && next < min) next = min\n if (typeof max === 'number' && next > max) next = max\n return Math.round(next * factor) / factor\n },\n [factor, max, min],\n )\n\n const commitValue = React.useCallback(\n (next: number | null) => {\n if (!isControlled) setInternalValue(next)\n onChange?.(next)\n },\n [isControlled, onChange],\n )\n\n const formatNumber = React.useCallback(\n (n: number) => (precision > 0 ? n.toFixed(precision) : String(n)),\n [precision],\n )\n\n const adjust = React.useCallback(\n (direction: 1 | -1) => {\n const current = typeof value === 'number' ? value : 0\n commitValue(clamp(current + direction * step))\n },\n [clamp, commitValue, step, value],\n )\n\n const handleInputChange = (event: React.ChangeEvent<HTMLInputElement>) => {\n const text = event.target.value\n if (text === '' || text === '-') {\n commitValue(null)\n return\n }\n const parsed = Number(text)\n if (!Number.isFinite(parsed)) return\n commitValue(clamp(parsed))\n }\n\n const handleKeyDown = (event: React.KeyboardEvent<HTMLInputElement>) => {\n if (event.key === 'ArrowUp') {\n event.preventDefault()\n adjust(1)\n } else if (event.key === 'ArrowDown') {\n event.preventDefault()\n adjust(-1)\n }\n }\n\n const incrementDisabled =\n disabled || (typeof max === 'number' && value !== null && value >= max)\n const decrementDisabled =\n disabled || (typeof min === 'number' && value !== null && value <= min)\n\n return (\n <div\n className={cn(counterWrapperVariants({ size }), className)}\n data-slot=\"counter-input\"\n >\n <button\n type=\"button\"\n onClick={() => adjust(-1)}\n disabled={decrementDisabled}\n aria-label={decrementAriaLabel}\n className={cn(counterButtonVariants({ size }))}\n data-slot=\"counter-input-decrement\"\n >\n <Minus aria-hidden=\"true\" />\n </button>\n <input\n ref={ref}\n type=\"number\"\n inputMode=\"decimal\"\n value={value === null ? '' : formatNumber(value)}\n onChange={handleInputChange}\n onKeyDown={handleKeyDown}\n disabled={disabled}\n placeholder={placeholder}\n min={min}\n max={max}\n step={step}\n className={cn(counterInputElementVariants({ size }), inputClassName)}\n {...rest}\n />\n <button\n type=\"button\"\n onClick={() => adjust(1)}\n disabled={incrementDisabled}\n aria-label={incrementAriaLabel}\n className={cn(counterButtonVariants({ size }))}\n data-slot=\"counter-input-increment\"\n >\n <Plus aria-hidden=\"true\" />\n </button>\n </div>\n )\n },\n)\n\nCounterInput.displayName = 'CounterInput'\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import {
|
|
2
|
+
startOfDay,
|
|
3
|
+
endOfDay,
|
|
4
|
+
startOfMonth,
|
|
5
|
+
startOfYear,
|
|
6
|
+
subDays,
|
|
7
|
+
subMonths,
|
|
8
|
+
subYears
|
|
9
|
+
} from "date-fns";
|
|
10
|
+
function defaultDateRangePresets() {
|
|
11
|
+
return [
|
|
12
|
+
{
|
|
13
|
+
id: "today",
|
|
14
|
+
labelKey: "ui.dateRangePicker.presets.today",
|
|
15
|
+
range: (ref = /* @__PURE__ */ new Date()) => ({ start: startOfDay(ref), end: endOfDay(ref) })
|
|
16
|
+
},
|
|
17
|
+
{
|
|
18
|
+
id: "last_7_days",
|
|
19
|
+
labelKey: "ui.dateRangePicker.presets.last7Days",
|
|
20
|
+
range: (ref = /* @__PURE__ */ new Date()) => ({
|
|
21
|
+
start: startOfDay(subDays(ref, 6)),
|
|
22
|
+
end: endOfDay(ref)
|
|
23
|
+
})
|
|
24
|
+
},
|
|
25
|
+
{
|
|
26
|
+
id: "last_30_days",
|
|
27
|
+
labelKey: "ui.dateRangePicker.presets.last30Days",
|
|
28
|
+
range: (ref = /* @__PURE__ */ new Date()) => ({
|
|
29
|
+
start: startOfDay(subDays(ref, 29)),
|
|
30
|
+
end: endOfDay(ref)
|
|
31
|
+
})
|
|
32
|
+
},
|
|
33
|
+
{
|
|
34
|
+
id: "last_3_months",
|
|
35
|
+
labelKey: "ui.dateRangePicker.presets.last3Months",
|
|
36
|
+
range: (ref = /* @__PURE__ */ new Date()) => ({
|
|
37
|
+
start: startOfDay(subMonths(ref, 3)),
|
|
38
|
+
end: endOfDay(ref)
|
|
39
|
+
})
|
|
40
|
+
},
|
|
41
|
+
{
|
|
42
|
+
id: "last_12_months",
|
|
43
|
+
labelKey: "ui.dateRangePicker.presets.last12Months",
|
|
44
|
+
range: (ref = /* @__PURE__ */ new Date()) => ({
|
|
45
|
+
start: startOfDay(subYears(ref, 1)),
|
|
46
|
+
end: endOfDay(ref)
|
|
47
|
+
})
|
|
48
|
+
},
|
|
49
|
+
{
|
|
50
|
+
id: "month_to_date",
|
|
51
|
+
labelKey: "ui.dateRangePicker.presets.monthToDate",
|
|
52
|
+
range: (ref = /* @__PURE__ */ new Date()) => ({
|
|
53
|
+
start: startOfMonth(ref),
|
|
54
|
+
end: endOfDay(ref)
|
|
55
|
+
})
|
|
56
|
+
},
|
|
57
|
+
{
|
|
58
|
+
id: "year_to_date",
|
|
59
|
+
labelKey: "ui.dateRangePicker.presets.yearToDate",
|
|
60
|
+
range: (ref = /* @__PURE__ */ new Date()) => ({
|
|
61
|
+
start: startOfYear(ref),
|
|
62
|
+
end: endOfDay(ref)
|
|
63
|
+
})
|
|
64
|
+
},
|
|
65
|
+
{
|
|
66
|
+
id: "all_time",
|
|
67
|
+
labelKey: "ui.dateRangePicker.presets.allTime",
|
|
68
|
+
range: (ref = /* @__PURE__ */ new Date()) => ({
|
|
69
|
+
// Symbolic "all time": from epoch to end of reference day.
|
|
70
|
+
start: /* @__PURE__ */ new Date(0),
|
|
71
|
+
end: endOfDay(ref)
|
|
72
|
+
})
|
|
73
|
+
}
|
|
74
|
+
];
|
|
75
|
+
}
|
|
76
|
+
export {
|
|
77
|
+
defaultDateRangePresets
|
|
78
|
+
};
|
|
79
|
+
//# sourceMappingURL=date-picker-helpers.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../src/primitives/date-picker-helpers.ts"],
|
|
4
|
+
"sourcesContent": ["import {\n startOfDay,\n endOfDay,\n startOfMonth,\n startOfYear,\n subDays,\n subMonths,\n subYears,\n} from 'date-fns'\nimport type { DateRange } from '../backend/date-range/dateRanges'\n\nexport type DateRangePresetItem = {\n id: string\n labelKey: string\n range: (referenceDate?: Date) => DateRange\n}\n\n/**\n * Returns the canonical 8 date-range presets aligned with the Figma\n * Range Picker spec (`446:7412` Period Range track).\n *\n * The list is intentionally shorter than `DATE_RANGE_OPTIONS` from\n * `@open-mercato/ui/backend/date-range`: that constant powers\n * dashboard/analytics modules with 13 presets (today, yesterday,\n * this/last week/month/quarter/year, last 7/30/90 days), but the Figma\n * Range Picker UI exposes 8 options optimised for filter UX (today plus\n * sliding windows and month/year-to-date).\n *\n * Used by `<DateRangePicker>` as the default `presets` value.\n */\nexport function defaultDateRangePresets(): DateRangePresetItem[] {\n return [\n {\n id: 'today',\n labelKey: 'ui.dateRangePicker.presets.today',\n range: (ref = new Date()) => ({ start: startOfDay(ref), end: endOfDay(ref) }),\n },\n {\n id: 'last_7_days',\n labelKey: 'ui.dateRangePicker.presets.last7Days',\n range: (ref = new Date()) => ({\n start: startOfDay(subDays(ref, 6)),\n end: endOfDay(ref),\n }),\n },\n {\n id: 'last_30_days',\n labelKey: 'ui.dateRangePicker.presets.last30Days',\n range: (ref = new Date()) => ({\n start: startOfDay(subDays(ref, 29)),\n end: endOfDay(ref),\n }),\n },\n {\n id: 'last_3_months',\n labelKey: 'ui.dateRangePicker.presets.last3Months',\n range: (ref = new Date()) => ({\n start: startOfDay(subMonths(ref, 3)),\n end: endOfDay(ref),\n }),\n },\n {\n id: 'last_12_months',\n labelKey: 'ui.dateRangePicker.presets.last12Months',\n range: (ref = new Date()) => ({\n start: startOfDay(subYears(ref, 1)),\n end: endOfDay(ref),\n }),\n },\n {\n id: 'month_to_date',\n labelKey: 'ui.dateRangePicker.presets.monthToDate',\n range: (ref = new Date()) => ({\n start: startOfMonth(ref),\n end: endOfDay(ref),\n }),\n },\n {\n id: 'year_to_date',\n labelKey: 'ui.dateRangePicker.presets.yearToDate',\n range: (ref = new Date()) => ({\n start: startOfYear(ref),\n end: endOfDay(ref),\n }),\n },\n {\n id: 'all_time',\n labelKey: 'ui.dateRangePicker.presets.allTime',\n range: (ref = new Date()) => ({\n // Symbolic \"all time\": from epoch to end of reference day.\n start: new Date(0),\n end: endOfDay(ref),\n }),\n },\n ]\n}\n"],
|
|
5
|
+
"mappings": "AAAA;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AAsBA,SAAS,0BAAiD;AAC/D,SAAO;AAAA,IACL;AAAA,MACE,IAAI;AAAA,MACJ,UAAU;AAAA,MACV,OAAO,CAAC,MAAM,oBAAI,KAAK,OAAO,EAAE,OAAO,WAAW,GAAG,GAAG,KAAK,SAAS,GAAG,EAAE;AAAA,IAC7E;AAAA,IACA;AAAA,MACE,IAAI;AAAA,MACJ,UAAU;AAAA,MACV,OAAO,CAAC,MAAM,oBAAI,KAAK,OAAO;AAAA,QAC5B,OAAO,WAAW,QAAQ,KAAK,CAAC,CAAC;AAAA,QACjC,KAAK,SAAS,GAAG;AAAA,MACnB;AAAA,IACF;AAAA,IACA;AAAA,MACE,IAAI;AAAA,MACJ,UAAU;AAAA,MACV,OAAO,CAAC,MAAM,oBAAI,KAAK,OAAO;AAAA,QAC5B,OAAO,WAAW,QAAQ,KAAK,EAAE,CAAC;AAAA,QAClC,KAAK,SAAS,GAAG;AAAA,MACnB;AAAA,IACF;AAAA,IACA;AAAA,MACE,IAAI;AAAA,MACJ,UAAU;AAAA,MACV,OAAO,CAAC,MAAM,oBAAI,KAAK,OAAO;AAAA,QAC5B,OAAO,WAAW,UAAU,KAAK,CAAC,CAAC;AAAA,QACnC,KAAK,SAAS,GAAG;AAAA,MACnB;AAAA,IACF;AAAA,IACA;AAAA,MACE,IAAI;AAAA,MACJ,UAAU;AAAA,MACV,OAAO,CAAC,MAAM,oBAAI,KAAK,OAAO;AAAA,QAC5B,OAAO,WAAW,SAAS,KAAK,CAAC,CAAC;AAAA,QAClC,KAAK,SAAS,GAAG;AAAA,MACnB;AAAA,IACF;AAAA,IACA;AAAA,MACE,IAAI;AAAA,MACJ,UAAU;AAAA,MACV,OAAO,CAAC,MAAM,oBAAI,KAAK,OAAO;AAAA,QAC5B,OAAO,aAAa,GAAG;AAAA,QACvB,KAAK,SAAS,GAAG;AAAA,MACnB;AAAA,IACF;AAAA,IACA;AAAA,MACE,IAAI;AAAA,MACJ,UAAU;AAAA,MACV,OAAO,CAAC,MAAM,oBAAI,KAAK,OAAO;AAAA,QAC5B,OAAO,YAAY,GAAG;AAAA,QACtB,KAAK,SAAS,GAAG;AAAA,MACnB;AAAA,IACF;AAAA,IACA;AAAA,MACE,IAAI;AAAA,MACJ,UAAU;AAAA,MACV,OAAO,CAAC,MAAM,oBAAI,KAAK,OAAO;AAAA;AAAA,QAE5B,OAAO,oBAAI,KAAK,CAAC;AAAA,QACjB,KAAK,SAAS,GAAG;AAAA,MACnB;AAAA,IACF;AAAA,EACF;AACF;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -0,0 +1,216 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
3
|
+
import * as React from "react";
|
|
4
|
+
import { format } from "date-fns";
|
|
5
|
+
import { CalendarIcon } from "lucide-react";
|
|
6
|
+
import { cn } from "@open-mercato/shared/lib/utils";
|
|
7
|
+
import { useT } from "@open-mercato/shared/lib/i18n/context";
|
|
8
|
+
import { Popover, PopoverContent, PopoverTrigger } from "./popover.js";
|
|
9
|
+
import { Calendar } from "./calendar.js";
|
|
10
|
+
import { Button } from "./button.js";
|
|
11
|
+
import { LinkButton } from "./link-button.js";
|
|
12
|
+
import { TimeInput } from "../backend/inputs/TimeInput.js";
|
|
13
|
+
const DAY_FIRST_LOCALE_CODES = /* @__PURE__ */ new Set([
|
|
14
|
+
"pl",
|
|
15
|
+
"de",
|
|
16
|
+
"fr",
|
|
17
|
+
"es",
|
|
18
|
+
"it",
|
|
19
|
+
"pt",
|
|
20
|
+
"nl",
|
|
21
|
+
"ru",
|
|
22
|
+
"cs",
|
|
23
|
+
"sk",
|
|
24
|
+
"hu",
|
|
25
|
+
"ro"
|
|
26
|
+
]);
|
|
27
|
+
function deriveDisplayFormat(locale, withTime) {
|
|
28
|
+
const code = locale?.code?.split("-")[0]?.toLowerCase() ?? "";
|
|
29
|
+
const dateFmt = code && DAY_FIRST_LOCALE_CODES.has(code) ? "d MMM yyyy" : "MMM d, yyyy";
|
|
30
|
+
return withTime ? `${dateFmt} HH:mm` : dateFmt;
|
|
31
|
+
}
|
|
32
|
+
function extractTime(date) {
|
|
33
|
+
return `${String(date.getHours()).padStart(2, "0")}:${String(date.getMinutes()).padStart(2, "0")}`;
|
|
34
|
+
}
|
|
35
|
+
function applyTimeToDate(base, time) {
|
|
36
|
+
const [hourStr = "0", minuteStr = "0"] = time.split(":");
|
|
37
|
+
const hour = parseInt(hourStr, 10);
|
|
38
|
+
const minute = parseInt(minuteStr, 10);
|
|
39
|
+
const next = new Date(base);
|
|
40
|
+
next.setHours(isNaN(hour) ? 0 : hour, isNaN(minute) ? 0 : minute, 0, 0);
|
|
41
|
+
return next;
|
|
42
|
+
}
|
|
43
|
+
function startOfDay(date) {
|
|
44
|
+
const next = new Date(date);
|
|
45
|
+
next.setHours(0, 0, 0, 0);
|
|
46
|
+
return next;
|
|
47
|
+
}
|
|
48
|
+
function DatePicker({
|
|
49
|
+
value,
|
|
50
|
+
onChange,
|
|
51
|
+
placeholder,
|
|
52
|
+
size = "default",
|
|
53
|
+
disabled = false,
|
|
54
|
+
readOnly = false,
|
|
55
|
+
footer = "apply-cancel",
|
|
56
|
+
closeOnSelect,
|
|
57
|
+
showTodayButton = true,
|
|
58
|
+
showClearButton = true,
|
|
59
|
+
withTime = false,
|
|
60
|
+
minuteStep = 1,
|
|
61
|
+
align = "start",
|
|
62
|
+
minDate,
|
|
63
|
+
maxDate,
|
|
64
|
+
locale,
|
|
65
|
+
displayFormat,
|
|
66
|
+
className,
|
|
67
|
+
popoverClassName,
|
|
68
|
+
id,
|
|
69
|
+
name,
|
|
70
|
+
required,
|
|
71
|
+
"aria-label": ariaLabel,
|
|
72
|
+
"aria-describedby": ariaDescribedBy
|
|
73
|
+
}) {
|
|
74
|
+
const resolvedCloseOnSelect = closeOnSelect ?? footer === "today-clear";
|
|
75
|
+
const t = useT();
|
|
76
|
+
const [open, setOpen] = React.useState(false);
|
|
77
|
+
const [draft, setDraft] = React.useState(value ?? null);
|
|
78
|
+
const isInteractive = !disabled && !readOnly;
|
|
79
|
+
const useDraft = footer === "apply-cancel";
|
|
80
|
+
React.useEffect(() => {
|
|
81
|
+
if (open) setDraft(value ?? null);
|
|
82
|
+
}, [open, value]);
|
|
83
|
+
const resolvedFormat = displayFormat ?? deriveDisplayFormat(locale, withTime);
|
|
84
|
+
const placeholderText = placeholder ?? (withTime ? t("ui.dateTimePicker.placeholder", "Pick date and time") : t("ui.datePicker.placeholder", "Pick a date"));
|
|
85
|
+
const formattedValue = React.useMemo(() => {
|
|
86
|
+
if (!value) return null;
|
|
87
|
+
try {
|
|
88
|
+
return format(value, resolvedFormat, locale ? { locale } : void 0);
|
|
89
|
+
} catch {
|
|
90
|
+
return null;
|
|
91
|
+
}
|
|
92
|
+
}, [value, resolvedFormat, locale]);
|
|
93
|
+
const handleDaySelect = React.useCallback(
|
|
94
|
+
(day) => {
|
|
95
|
+
if (!day || !isInteractive) return;
|
|
96
|
+
const reference = withTime ? useDraft ? draft : value : null;
|
|
97
|
+
const base = withTime ? applyTimeToDate(day, reference ? extractTime(reference) : "00:00") : startOfDay(day);
|
|
98
|
+
if (useDraft) {
|
|
99
|
+
setDraft(base);
|
|
100
|
+
} else {
|
|
101
|
+
onChange(base);
|
|
102
|
+
if (footer === "none" || resolvedCloseOnSelect) setOpen(false);
|
|
103
|
+
}
|
|
104
|
+
},
|
|
105
|
+
[isInteractive, withTime, useDraft, draft, value, footer, resolvedCloseOnSelect, onChange]
|
|
106
|
+
);
|
|
107
|
+
const handleTimeChange = React.useCallback(
|
|
108
|
+
(time) => {
|
|
109
|
+
const target = useDraft ? draft : value;
|
|
110
|
+
if (!target) return;
|
|
111
|
+
const next = applyTimeToDate(target, time);
|
|
112
|
+
if (useDraft) setDraft(next);
|
|
113
|
+
else onChange(next);
|
|
114
|
+
},
|
|
115
|
+
[useDraft, draft, value, onChange]
|
|
116
|
+
);
|
|
117
|
+
const handleApply = React.useCallback(() => {
|
|
118
|
+
onChange(draft);
|
|
119
|
+
setOpen(false);
|
|
120
|
+
}, [draft, onChange]);
|
|
121
|
+
const handleCancel = React.useCallback(() => {
|
|
122
|
+
setDraft(value ?? null);
|
|
123
|
+
setOpen(false);
|
|
124
|
+
}, [value]);
|
|
125
|
+
const handleToday = React.useCallback(() => {
|
|
126
|
+
const today = withTime ? /* @__PURE__ */ new Date() : startOfDay(/* @__PURE__ */ new Date());
|
|
127
|
+
onChange(today);
|
|
128
|
+
setOpen(false);
|
|
129
|
+
}, [withTime, onChange]);
|
|
130
|
+
const handleClear = React.useCallback(() => {
|
|
131
|
+
onChange(null);
|
|
132
|
+
setOpen(false);
|
|
133
|
+
}, [onChange]);
|
|
134
|
+
const disabledMatcher = React.useMemo(() => {
|
|
135
|
+
if (!minDate && !maxDate) return void 0;
|
|
136
|
+
const matchers = [];
|
|
137
|
+
if (minDate) matchers.push({ before: minDate });
|
|
138
|
+
if (maxDate) matchers.push({ after: maxDate });
|
|
139
|
+
return matchers;
|
|
140
|
+
}, [minDate, maxDate]);
|
|
141
|
+
const heightClass = size === "sm" ? "h-8 px-2.5 text-xs" : "h-9 px-3 text-sm";
|
|
142
|
+
const selectedDate = useDraft ? draft : value;
|
|
143
|
+
return /* @__PURE__ */ jsxs(Popover, { open, onOpenChange: isInteractive ? setOpen : void 0, children: [
|
|
144
|
+
/* @__PURE__ */ jsx(PopoverTrigger, { asChild: true, children: /* @__PURE__ */ jsxs(
|
|
145
|
+
"button",
|
|
146
|
+
{
|
|
147
|
+
type: "button",
|
|
148
|
+
id,
|
|
149
|
+
name,
|
|
150
|
+
"aria-label": ariaLabel,
|
|
151
|
+
"aria-describedby": ariaDescribedBy,
|
|
152
|
+
"aria-haspopup": "dialog",
|
|
153
|
+
"aria-required": required ? true : void 0,
|
|
154
|
+
"data-crud-focus-target": "",
|
|
155
|
+
"data-slot": "date-picker-trigger",
|
|
156
|
+
disabled,
|
|
157
|
+
className: cn(
|
|
158
|
+
"w-full inline-flex items-center gap-2 rounded-md border border-input bg-background shadow-xs transition-colors text-left",
|
|
159
|
+
"focus-visible:outline-none focus-visible:shadow-focus focus-visible:border-foreground",
|
|
160
|
+
"hover:bg-muted/40",
|
|
161
|
+
"disabled:bg-bg-disabled disabled:border-border-disabled disabled:shadow-none disabled:hover:bg-bg-disabled disabled:cursor-not-allowed",
|
|
162
|
+
"aria-invalid:border-destructive",
|
|
163
|
+
heightClass,
|
|
164
|
+
readOnly && "cursor-default opacity-70",
|
|
165
|
+
!formattedValue && "text-muted-foreground",
|
|
166
|
+
className
|
|
167
|
+
),
|
|
168
|
+
onClick: isInteractive ? void 0 : (event) => event.preventDefault(),
|
|
169
|
+
children: [
|
|
170
|
+
/* @__PURE__ */ jsx(CalendarIcon, { className: "h-4 w-4 shrink-0 text-muted-foreground", "aria-hidden": "true" }),
|
|
171
|
+
/* @__PURE__ */ jsx("span", { className: "flex-1 truncate", children: formattedValue ?? placeholderText })
|
|
172
|
+
]
|
|
173
|
+
}
|
|
174
|
+
) }),
|
|
175
|
+
/* @__PURE__ */ jsxs(PopoverContent, { align, className: cn("w-auto p-0", popoverClassName), children: [
|
|
176
|
+
/* @__PURE__ */ jsx(
|
|
177
|
+
Calendar,
|
|
178
|
+
{
|
|
179
|
+
mode: "single",
|
|
180
|
+
selected: selectedDate ?? void 0,
|
|
181
|
+
onSelect: handleDaySelect,
|
|
182
|
+
locale,
|
|
183
|
+
disabled: disabledMatcher,
|
|
184
|
+
initialFocus: true
|
|
185
|
+
}
|
|
186
|
+
),
|
|
187
|
+
withTime && /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 border-t px-3 py-2", children: [
|
|
188
|
+
/* @__PURE__ */ jsxs("span", { className: "text-sm text-muted-foreground shrink-0", children: [
|
|
189
|
+
t("ui.datePicker.timeLabel", "Time"),
|
|
190
|
+
":"
|
|
191
|
+
] }),
|
|
192
|
+
/* @__PURE__ */ jsx(
|
|
193
|
+
TimeInput,
|
|
194
|
+
{
|
|
195
|
+
value: selectedDate ? extractTime(selectedDate) : void 0,
|
|
196
|
+
onChange: handleTimeChange,
|
|
197
|
+
minuteStep,
|
|
198
|
+
disabled: !isInteractive || !selectedDate
|
|
199
|
+
}
|
|
200
|
+
)
|
|
201
|
+
] }),
|
|
202
|
+
footer === "apply-cancel" && /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-end gap-2 border-t px-3 py-2", children: [
|
|
203
|
+
/* @__PURE__ */ jsx(Button, { type: "button", variant: "outline", size: "sm", onClick: handleCancel, children: t("ui.datePicker.cancelButton", "Cancel") }),
|
|
204
|
+
/* @__PURE__ */ jsx(Button, { type: "button", size: "sm", onClick: handleApply, children: t("ui.datePicker.applyButton", "Apply") })
|
|
205
|
+
] }),
|
|
206
|
+
footer === "today-clear" && (showTodayButton || showClearButton) && /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between gap-2 border-t px-3 py-2", children: [
|
|
207
|
+
showTodayButton ? /* @__PURE__ */ jsx(LinkButton, { type: "button", variant: "primary", onClick: handleToday, children: t("ui.datePicker.todayButton", "Today") }) : null,
|
|
208
|
+
showClearButton ? /* @__PURE__ */ jsx(LinkButton, { type: "button", variant: "gray", onClick: handleClear, className: "ml-auto", children: t("ui.datePicker.clearButton", "Clear") }) : null
|
|
209
|
+
] })
|
|
210
|
+
] })
|
|
211
|
+
] });
|
|
212
|
+
}
|
|
213
|
+
export {
|
|
214
|
+
DatePicker
|
|
215
|
+
};
|
|
216
|
+
//# sourceMappingURL=date-picker.js.map
|