@acronis-platform/ui-react 0.62.0 → 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/components/ui/alert/alert.js +115 -57
- package/dist/components/ui/alert/alert.js.map +1 -1
- package/dist/components/ui/button-group/button-group.js +57 -0
- package/dist/components/ui/button-group/button-group.js.map +1 -0
- package/dist/components/ui/button-icon-menu/button-icon-menu.js +26 -0
- package/dist/components/ui/button-icon-menu/button-icon-menu.js.map +1 -0
- package/dist/components/ui/calendar-panel/calendar-panel.js.map +1 -1
- package/dist/components/ui/chip/chip.js +33 -33
- package/dist/components/ui/chip/chip.js.map +1 -1
- package/dist/components/ui/date-range-picker/date-range-picker-utils.js +11 -23
- package/dist/components/ui/date-range-picker/date-range-picker-utils.js.map +1 -1
- package/dist/components/ui/date-range-picker/date-range-picker.js +94 -134
- package/dist/components/ui/date-range-picker/date-range-picker.js.map +1 -1
- package/dist/components/ui/dropdown-menu/dropdown-menu.js +129 -72
- package/dist/components/ui/dropdown-menu/dropdown-menu.js.map +1 -1
- package/dist/components/ui/filter-chips/filter-chips.js +44 -0
- package/dist/components/ui/filter-chips/filter-chips.js.map +1 -0
- package/dist/components/ui/filter-search/filter-search.js +184 -138
- package/dist/components/ui/filter-search/filter-search.js.map +1 -1
- package/dist/components/ui/fitted-actions/fitted-actions.js +139 -0
- package/dist/components/ui/fitted-actions/fitted-actions.js.map +1 -0
- package/dist/components/ui/input-date-picker/input-date-picker.js +103 -93
- package/dist/components/ui/input-date-picker/input-date-picker.js.map +1 -1
- package/dist/components/ui/input-password/input-password.js +76 -66
- package/dist/components/ui/input-password/input-password.js.map +1 -1
- package/dist/components/ui/input-search/input-search.js +9 -9
- package/dist/components/ui/input-search/input-search.js.map +1 -1
- package/dist/components/ui/input-select/input-select.js +8 -8
- package/dist/components/ui/input-select/input-select.js.map +1 -1
- package/dist/components/ui/input-text/input-text.js +77 -66
- package/dist/components/ui/input-text/input-text.js.map +1 -1
- package/dist/components/ui/input-text-area/input-text-area.js +76 -66
- package/dist/components/ui/input-text-area/input-text-area.js.map +1 -1
- package/dist/components/ui/link/link.js +50 -35
- package/dist/components/ui/link/link.js.map +1 -1
- package/dist/components/ui/number-field/number-field.js +1 -1
- package/dist/components/ui/number-field/number-field.js.map +1 -1
- package/dist/components/ui/popover/popover.js +75 -56
- package/dist/components/ui/popover/popover.js.map +1 -1
- package/dist/components/ui/scroll-area/scroll-area.js +46 -30
- package/dist/components/ui/scroll-area/scroll-area.js.map +1 -1
- package/dist/components/ui/timer/timer.js +47 -0
- package/dist/components/ui/timer/timer.js.map +1 -0
- package/dist/components/ui/toast/toast.js +168 -61
- package/dist/components/ui/toast/toast.js.map +1 -1
- package/dist/components/ui/truncate-text/middle-truncate.js +20 -0
- package/dist/components/ui/truncate-text/middle-truncate.js.map +1 -0
- package/dist/components/ui/truncate-text/text-width.js +12 -0
- package/dist/components/ui/truncate-text/text-width.js.map +1 -0
- package/dist/components/ui/truncate-text/truncate-text.js +152 -0
- package/dist/components/ui/truncate-text/truncate-text.js.map +1 -0
- package/dist/index.js +505 -473
- package/dist/index.js.map +1 -1
- package/dist/node_modules/.pnpm/date-fns@4.3.0/node_modules/date-fns/addDays.js +5 -5
- package/dist/node_modules/.pnpm/date-fns@4.3.0/node_modules/date-fns/addDays.js.map +1 -1
- package/dist/node_modules/.pnpm/date-fns@4.3.0/node_modules/date-fns/constants.js +3 -6
- package/dist/node_modules/.pnpm/date-fns@4.3.0/node_modules/date-fns/constants.js.map +1 -1
- package/dist/react.js +505 -473
- package/dist/react.js.map +1 -1
- package/dist/src/components/ui/alert/alert.d.ts +34 -3
- package/dist/src/components/ui/alert/index.d.ts +2 -2
- package/dist/src/components/ui/button/button.d.ts +1 -1
- package/dist/src/components/ui/button-group/button-group.d.ts +38 -0
- package/dist/src/components/ui/button-group/index.d.ts +1 -0
- package/dist/src/components/ui/button-icon/button-icon.d.ts +1 -1
- package/dist/src/components/ui/button-icon-menu/button-icon-menu.d.ts +28 -0
- package/dist/src/components/ui/button-icon-menu/index.d.ts +1 -0
- package/dist/src/components/ui/button-menu/button-menu.d.ts +1 -1
- package/dist/src/components/ui/calendar-panel/calendar-panel.d.ts +2 -2
- package/dist/src/components/ui/chip/chip.d.ts +1 -1
- package/dist/src/components/ui/date-range-picker/date-range-picker-utils.d.ts +10 -16
- package/dist/src/components/ui/date-range-picker/date-range-picker.d.ts +46 -2
- package/dist/src/components/ui/dropdown-menu/dropdown-menu.d.ts +8 -1
- package/dist/src/components/ui/dropdown-menu/index.d.ts +1 -1
- package/dist/src/components/ui/filter-chips/filter-chips.d.ts +25 -0
- package/dist/src/components/ui/filter-chips/index.d.ts +1 -0
- package/dist/src/components/ui/filter-search/filter-search.d.ts +39 -1
- package/dist/src/components/ui/fitted-actions/fitted-actions.d.ts +50 -0
- package/dist/src/components/ui/fitted-actions/fitted-actions.docs.d.ts +45 -0
- package/dist/src/components/ui/fitted-actions/index.d.ts +1 -0
- package/dist/src/components/ui/link/index.d.ts +1 -1
- package/dist/src/components/ui/link/link.d.ts +22 -4
- package/dist/src/components/ui/metric/metric.d.ts +1 -1
- package/dist/src/components/ui/popover/popover.d.ts +30 -1
- package/dist/src/components/ui/popover/popover.docs.d.ts +27 -2
- package/dist/src/components/ui/scroll-area/scroll-area.d.ts +24 -0
- package/dist/src/components/ui/tag/tag.d.ts +1 -1
- package/dist/src/components/ui/timer/index.d.ts +1 -0
- package/dist/src/components/ui/timer/timer.d.ts +28 -0
- package/dist/src/components/ui/toast/index.d.ts +1 -1
- package/dist/src/components/ui/toast/toast.d.ts +51 -18
- package/dist/src/components/ui/toast/toast.docs.d.ts +4 -0
- package/dist/src/components/ui/trend-indicator/trend-indicator.d.ts +1 -1
- package/dist/src/components/ui/truncate-text/__tests__/middle-truncate.test.d.ts +1 -0
- package/dist/src/components/ui/truncate-text/index.d.ts +3 -0
- package/dist/src/components/ui/truncate-text/middle-truncate.d.ts +13 -0
- package/dist/src/components/ui/truncate-text/text-width.d.ts +11 -0
- package/dist/src/components/ui/truncate-text/truncate-text.d.ts +45 -0
- package/dist/src/components/ui/truncate-text/truncate-text.docs.d.ts +35 -0
- package/dist/src/index.d.ts +6 -0
- package/dist/ui-react.css +1 -1
- package/package.json +3 -3
- package/dist/node_modules/.pnpm/date-fns@4.3.0/node_modules/date-fns/getDefaultOptions.js +0 -8
- package/dist/node_modules/.pnpm/date-fns@4.3.0/node_modules/date-fns/getDefaultOptions.js.map +0 -1
- package/dist/node_modules/.pnpm/date-fns@4.3.0/node_modules/date-fns/getISODay.js +0 -9
- package/dist/node_modules/.pnpm/date-fns@4.3.0/node_modules/date-fns/getISODay.js.map +0 -1
- package/dist/node_modules/.pnpm/date-fns@4.3.0/node_modules/date-fns/parse/_lib/Parser.js +0 -23
- package/dist/node_modules/.pnpm/date-fns@4.3.0/node_modules/date-fns/parse/_lib/Parser.js.map +0 -1
- package/dist/node_modules/.pnpm/date-fns@4.3.0/node_modules/date-fns/parse/_lib/Setter.js +0 -42
- package/dist/node_modules/.pnpm/date-fns@4.3.0/node_modules/date-fns/parse/_lib/Setter.js.map +0 -1
- package/dist/node_modules/.pnpm/date-fns@4.3.0/node_modules/date-fns/parse/_lib/constants.js +0 -50
- package/dist/node_modules/.pnpm/date-fns@4.3.0/node_modules/date-fns/parse/_lib/constants.js.map +0 -1
- package/dist/node_modules/.pnpm/date-fns@4.3.0/node_modules/date-fns/parse/_lib/parsers/AMPMMidnightParser.js +0 -50
- package/dist/node_modules/.pnpm/date-fns@4.3.0/node_modules/date-fns/parse/_lib/parsers/AMPMMidnightParser.js.map +0 -1
- package/dist/node_modules/.pnpm/date-fns@4.3.0/node_modules/date-fns/parse/_lib/parsers/AMPMParser.js +0 -50
- package/dist/node_modules/.pnpm/date-fns@4.3.0/node_modules/date-fns/parse/_lib/parsers/AMPMParser.js.map +0 -1
- package/dist/node_modules/.pnpm/date-fns@4.3.0/node_modules/date-fns/parse/_lib/parsers/DateParser.js +0 -62
- package/dist/node_modules/.pnpm/date-fns@4.3.0/node_modules/date-fns/parse/_lib/parsers/DateParser.js.map +0 -1
- package/dist/node_modules/.pnpm/date-fns@4.3.0/node_modules/date-fns/parse/_lib/parsers/DayOfYearParser.js +0 -52
- package/dist/node_modules/.pnpm/date-fns@4.3.0/node_modules/date-fns/parse/_lib/parsers/DayOfYearParser.js.map +0 -1
- package/dist/node_modules/.pnpm/date-fns@4.3.0/node_modules/date-fns/parse/_lib/parsers/DayParser.js +0 -50
- package/dist/node_modules/.pnpm/date-fns@4.3.0/node_modules/date-fns/parse/_lib/parsers/DayParser.js.map +0 -1
- package/dist/node_modules/.pnpm/date-fns@4.3.0/node_modules/date-fns/parse/_lib/parsers/DayPeriodParser.js +0 -50
- package/dist/node_modules/.pnpm/date-fns@4.3.0/node_modules/date-fns/parse/_lib/parsers/DayPeriodParser.js.map +0 -1
- package/dist/node_modules/.pnpm/date-fns@4.3.0/node_modules/date-fns/parse/_lib/parsers/EraParser.js +0 -34
- package/dist/node_modules/.pnpm/date-fns@4.3.0/node_modules/date-fns/parse/_lib/parsers/EraParser.js.map +0 -1
- package/dist/node_modules/.pnpm/date-fns@4.3.0/node_modules/date-fns/parse/_lib/parsers/ExtendedYearParser.js +0 -22
- package/dist/node_modules/.pnpm/date-fns@4.3.0/node_modules/date-fns/parse/_lib/parsers/ExtendedYearParser.js.map +0 -1
- package/dist/node_modules/.pnpm/date-fns@4.3.0/node_modules/date-fns/parse/_lib/parsers/FractionOfSecondParser.js +0 -23
- package/dist/node_modules/.pnpm/date-fns@4.3.0/node_modules/date-fns/parse/_lib/parsers/FractionOfSecondParser.js.map +0 -1
- package/dist/node_modules/.pnpm/date-fns@4.3.0/node_modules/date-fns/parse/_lib/parsers/Hour0To11Parser.js +0 -33
- package/dist/node_modules/.pnpm/date-fns@4.3.0/node_modules/date-fns/parse/_lib/parsers/Hour0To11Parser.js.map +0 -1
- package/dist/node_modules/.pnpm/date-fns@4.3.0/node_modules/date-fns/parse/_lib/parsers/Hour0to23Parser.js +0 -33
- package/dist/node_modules/.pnpm/date-fns@4.3.0/node_modules/date-fns/parse/_lib/parsers/Hour0to23Parser.js.map +0 -1
- package/dist/node_modules/.pnpm/date-fns@4.3.0/node_modules/date-fns/parse/_lib/parsers/Hour1To24Parser.js +0 -34
- package/dist/node_modules/.pnpm/date-fns@4.3.0/node_modules/date-fns/parse/_lib/parsers/Hour1To24Parser.js.map +0 -1
- package/dist/node_modules/.pnpm/date-fns@4.3.0/node_modules/date-fns/parse/_lib/parsers/Hour1to12Parser.js +0 -34
- package/dist/node_modules/.pnpm/date-fns@4.3.0/node_modules/date-fns/parse/_lib/parsers/Hour1to12Parser.js.map +0 -1
- package/dist/node_modules/.pnpm/date-fns@4.3.0/node_modules/date-fns/parse/_lib/parsers/ISODayParser.js +0 -106
- package/dist/node_modules/.pnpm/date-fns@4.3.0/node_modules/date-fns/parse/_lib/parsers/ISODayParser.js.map +0 -1
- package/dist/node_modules/.pnpm/date-fns@4.3.0/node_modules/date-fns/parse/_lib/parsers/ISOTimezoneParser.js +0 -49
- package/dist/node_modules/.pnpm/date-fns@4.3.0/node_modules/date-fns/parse/_lib/parsers/ISOTimezoneParser.js.map +0 -1
- package/dist/node_modules/.pnpm/date-fns@4.3.0/node_modules/date-fns/parse/_lib/parsers/ISOTimezoneWithZParser.js +0 -49
- package/dist/node_modules/.pnpm/date-fns@4.3.0/node_modules/date-fns/parse/_lib/parsers/ISOTimezoneWithZParser.js.map +0 -1
- package/dist/node_modules/.pnpm/date-fns@4.3.0/node_modules/date-fns/parse/_lib/parsers/ISOWeekParser.js +0 -50
- package/dist/node_modules/.pnpm/date-fns@4.3.0/node_modules/date-fns/parse/_lib/parsers/ISOWeekParser.js.map +0 -1
- package/dist/node_modules/.pnpm/date-fns@4.3.0/node_modules/date-fns/parse/_lib/parsers/ISOWeekYearParser.js +0 -41
- package/dist/node_modules/.pnpm/date-fns@4.3.0/node_modules/date-fns/parse/_lib/parsers/ISOWeekYearParser.js.map +0 -1
- package/dist/node_modules/.pnpm/date-fns@4.3.0/node_modules/date-fns/parse/_lib/parsers/LocalDayParser.js +0 -81
- package/dist/node_modules/.pnpm/date-fns@4.3.0/node_modules/date-fns/parse/_lib/parsers/LocalDayParser.js.map +0 -1
- package/dist/node_modules/.pnpm/date-fns@4.3.0/node_modules/date-fns/parse/_lib/parsers/LocalWeekParser.js +0 -49
- package/dist/node_modules/.pnpm/date-fns@4.3.0/node_modules/date-fns/parse/_lib/parsers/LocalWeekParser.js.map +0 -1
- package/dist/node_modules/.pnpm/date-fns@4.3.0/node_modules/date-fns/parse/_lib/parsers/LocalWeekYearParser.js +0 -70
- package/dist/node_modules/.pnpm/date-fns@4.3.0/node_modules/date-fns/parse/_lib/parsers/LocalWeekYearParser.js.map +0 -1
- package/dist/node_modules/.pnpm/date-fns@4.3.0/node_modules/date-fns/parse/_lib/parsers/MinuteParser.js +0 -33
- package/dist/node_modules/.pnpm/date-fns@4.3.0/node_modules/date-fns/parse/_lib/parsers/MinuteParser.js.map +0 -1
- package/dist/node_modules/.pnpm/date-fns@4.3.0/node_modules/date-fns/parse/_lib/parsers/MonthParser.js +0 -78
- package/dist/node_modules/.pnpm/date-fns@4.3.0/node_modules/date-fns/parse/_lib/parsers/MonthParser.js.map +0 -1
- package/dist/node_modules/.pnpm/date-fns@4.3.0/node_modules/date-fns/parse/_lib/parsers/QuarterParser.js +0 -76
- package/dist/node_modules/.pnpm/date-fns@4.3.0/node_modules/date-fns/parse/_lib/parsers/QuarterParser.js.map +0 -1
- package/dist/node_modules/.pnpm/date-fns@4.3.0/node_modules/date-fns/parse/_lib/parsers/SecondParser.js +0 -33
- package/dist/node_modules/.pnpm/date-fns@4.3.0/node_modules/date-fns/parse/_lib/parsers/SecondParser.js.map +0 -1
- package/dist/node_modules/.pnpm/date-fns@4.3.0/node_modules/date-fns/parse/_lib/parsers/StandAloneLocalDayParser.js +0 -81
- package/dist/node_modules/.pnpm/date-fns@4.3.0/node_modules/date-fns/parse/_lib/parsers/StandAloneLocalDayParser.js.map +0 -1
- package/dist/node_modules/.pnpm/date-fns@4.3.0/node_modules/date-fns/parse/_lib/parsers/StandAloneMonthParser.js +0 -78
- package/dist/node_modules/.pnpm/date-fns@4.3.0/node_modules/date-fns/parse/_lib/parsers/StandAloneMonthParser.js.map +0 -1
- package/dist/node_modules/.pnpm/date-fns@4.3.0/node_modules/date-fns/parse/_lib/parsers/StandAloneQuarterParser.js +0 -76
- package/dist/node_modules/.pnpm/date-fns@4.3.0/node_modules/date-fns/parse/_lib/parsers/StandAloneQuarterParser.js.map +0 -1
- package/dist/node_modules/.pnpm/date-fns@4.3.0/node_modules/date-fns/parse/_lib/parsers/TimestampMillisecondsParser.js +0 -23
- package/dist/node_modules/.pnpm/date-fns@4.3.0/node_modules/date-fns/parse/_lib/parsers/TimestampMillisecondsParser.js.map +0 -1
- package/dist/node_modules/.pnpm/date-fns@4.3.0/node_modules/date-fns/parse/_lib/parsers/TimestampSecondsParser.js +0 -23
- package/dist/node_modules/.pnpm/date-fns@4.3.0/node_modules/date-fns/parse/_lib/parsers/TimestampSecondsParser.js.map +0 -1
- package/dist/node_modules/.pnpm/date-fns@4.3.0/node_modules/date-fns/parse/_lib/parsers/YearParser.js +0 -50
- package/dist/node_modules/.pnpm/date-fns@4.3.0/node_modules/date-fns/parse/_lib/parsers/YearParser.js.map +0 -1
- package/dist/node_modules/.pnpm/date-fns@4.3.0/node_modules/date-fns/parse/_lib/parsers.js +0 -68
- package/dist/node_modules/.pnpm/date-fns@4.3.0/node_modules/date-fns/parse/_lib/parsers.js.map +0 -1
- package/dist/node_modules/.pnpm/date-fns@4.3.0/node_modules/date-fns/parse/_lib/utils.js +0 -104
- package/dist/node_modules/.pnpm/date-fns@4.3.0/node_modules/date-fns/parse/_lib/utils.js.map +0 -1
- package/dist/node_modules/.pnpm/date-fns@4.3.0/node_modules/date-fns/parse.js +0 -86
- package/dist/node_modules/.pnpm/date-fns@4.3.0/node_modules/date-fns/parse.js.map +0 -1
- package/dist/node_modules/.pnpm/date-fns@4.3.0/node_modules/date-fns/setDay.js +0 -12
- package/dist/node_modules/.pnpm/date-fns@4.3.0/node_modules/date-fns/setDay.js.map +0 -1
- package/dist/node_modules/.pnpm/date-fns@4.3.0/node_modules/date-fns/setISODay.js +0 -11
- package/dist/node_modules/.pnpm/date-fns@4.3.0/node_modules/date-fns/setISODay.js.map +0 -1
- package/dist/node_modules/.pnpm/date-fns@4.3.0/node_modules/date-fns/setISOWeek.js +0 -10
- package/dist/node_modules/.pnpm/date-fns@4.3.0/node_modules/date-fns/setISOWeek.js.map +0 -1
- package/dist/node_modules/.pnpm/date-fns@4.3.0/node_modules/date-fns/setWeek.js +0 -10
- package/dist/node_modules/.pnpm/date-fns@4.3.0/node_modules/date-fns/setWeek.js.map +0 -1
- package/dist/node_modules/.pnpm/date-fns@4.3.0/node_modules/date-fns/transpose.js +0 -18
- package/dist/node_modules/.pnpm/date-fns@4.3.0/node_modules/date-fns/transpose.js.map +0 -1
|
@@ -1,165 +1,211 @@
|
|
|
1
|
-
import { jsx as
|
|
2
|
-
import * as
|
|
3
|
-
import { ChevronDownIcon as
|
|
1
|
+
import { jsx as r, jsxs as d } from "react/jsx-runtime";
|
|
2
|
+
import * as i from "react";
|
|
3
|
+
import { ChevronDownIcon as M } from "@acronis-platform/icons-react/stroke-mono";
|
|
4
4
|
import { cn as u } from "../../../lib/utils.js";
|
|
5
|
-
import { deepEqual as
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
8
|
-
import { Popover as
|
|
9
|
-
|
|
10
|
-
|
|
5
|
+
import { deepEqual as T } from "../../../lib/deep-equal.js";
|
|
6
|
+
import { FilterChips as G, FilterChipsList as H, FilterChipsReset as K } from "../filter-chips/filter-chips.js";
|
|
7
|
+
import { Chip as Q } from "../chip/chip.js";
|
|
8
|
+
import { Popover as U, PopoverTrigger as W, PopoverContent as X } from "../popover/popover.js";
|
|
9
|
+
import { Button as h } from "../button/button.js";
|
|
10
|
+
const Y = i.forwardRef(
|
|
11
|
+
({ className: t, ...e }, n) => /* @__PURE__ */ r(
|
|
11
12
|
"div",
|
|
12
13
|
{
|
|
13
|
-
ref:
|
|
14
|
+
ref: n,
|
|
14
15
|
className: u("flex items-center gap-4", t),
|
|
15
16
|
...e
|
|
16
17
|
}
|
|
17
18
|
)
|
|
18
19
|
);
|
|
19
|
-
|
|
20
|
-
const
|
|
20
|
+
Y.displayName = "FilterSearch";
|
|
21
|
+
const Z = i.forwardRef(({ className: t, ...e }, n) => /* @__PURE__ */ r(
|
|
21
22
|
"div",
|
|
22
23
|
{
|
|
23
|
-
ref:
|
|
24
|
-
className: u(
|
|
24
|
+
ref: n,
|
|
25
|
+
className: u(
|
|
26
|
+
"flex h-8 min-w-px flex-1 items-center justify-end gap-4",
|
|
27
|
+
t
|
|
28
|
+
),
|
|
25
29
|
...e
|
|
26
30
|
}
|
|
27
31
|
));
|
|
28
|
-
|
|
29
|
-
const
|
|
30
|
-
function
|
|
31
|
-
const t =
|
|
32
|
+
Z.displayName = "FilterSearchActions";
|
|
33
|
+
const R = i.createContext(null);
|
|
34
|
+
function le() {
|
|
35
|
+
const t = i.useContext(R);
|
|
32
36
|
if (t === null)
|
|
33
37
|
throw new Error(
|
|
34
38
|
"useFilterSearchFilters must be used within a <FilterSearchFilters> popover."
|
|
35
39
|
);
|
|
36
40
|
return t;
|
|
37
41
|
}
|
|
38
|
-
const
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
},
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
{
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
42
|
+
const _ = i.forwardRef(
|
|
43
|
+
({
|
|
44
|
+
value: t,
|
|
45
|
+
onValueChange: e,
|
|
46
|
+
onApply: n,
|
|
47
|
+
label: s = "Filters",
|
|
48
|
+
resetFiltersLabel: b = "Reset filters",
|
|
49
|
+
cancelLabel: F = "Cancel",
|
|
50
|
+
applyLabel: x = "Apply",
|
|
51
|
+
children: v,
|
|
52
|
+
className: l,
|
|
53
|
+
contentClassName: S,
|
|
54
|
+
side: o,
|
|
55
|
+
align: p = "start",
|
|
56
|
+
sideOffset: w,
|
|
57
|
+
portalContainer: j,
|
|
58
|
+
collisionBoundary: O,
|
|
59
|
+
positionMethod: D,
|
|
60
|
+
...A
|
|
61
|
+
}, P) => {
|
|
62
|
+
const [$, C] = i.useState(!1), [c, m] = i.useState(t), E = (a) => {
|
|
63
|
+
m(t), C(a);
|
|
64
|
+
}, g = i.useCallback((a, N) => {
|
|
65
|
+
m((f) => {
|
|
66
|
+
if (N === void 0) {
|
|
67
|
+
if (!(a in f)) return f;
|
|
68
|
+
const y = { ...f };
|
|
69
|
+
return delete y[a], y;
|
|
70
|
+
}
|
|
71
|
+
return { ...f, [a]: N };
|
|
72
|
+
});
|
|
73
|
+
}, []), L = i.useMemo(
|
|
74
|
+
() => ({ filters: c, setFilter: g }),
|
|
75
|
+
[c, g]
|
|
76
|
+
), q = () => m({}), z = () => {
|
|
77
|
+
m(t), C(!1);
|
|
78
|
+
}, B = () => {
|
|
79
|
+
e(c), n == null || n(c), C(!1);
|
|
80
|
+
}, I = Object.keys(c).length === 0, J = T(c, t);
|
|
81
|
+
return /* @__PURE__ */ d(U, { open: $, onOpenChange: E, children: [
|
|
82
|
+
/* @__PURE__ */ d(
|
|
83
|
+
W,
|
|
84
|
+
{
|
|
85
|
+
ref: P,
|
|
86
|
+
render: /* @__PURE__ */ r(
|
|
87
|
+
h,
|
|
78
88
|
{
|
|
79
|
-
|
|
80
|
-
className:
|
|
89
|
+
variant: "secondary",
|
|
90
|
+
className: u(
|
|
91
|
+
"group data-[popup-open]:border-[var(--ui-button-secondary-container-border-color-active)] data-[popup-open]:bg-[var(--ui-button-secondary-container-color-active)] data-[popup-open]:text-[var(--ui-button-secondary-label-color-active)]",
|
|
92
|
+
l
|
|
93
|
+
),
|
|
94
|
+
...A
|
|
81
95
|
}
|
|
82
|
-
)
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
"form",
|
|
88
|
-
{
|
|
89
|
-
onSubmit: (i) => {
|
|
90
|
-
i.preventDefault(), j();
|
|
91
|
-
},
|
|
92
|
-
children: [
|
|
93
|
-
/* @__PURE__ */ n("div", { className: "flex max-h-80 flex-col gap-4 overflow-y-auto p-4", children: /* @__PURE__ */ n(C.Provider, { value: y, children: b }) }),
|
|
94
|
-
/* @__PURE__ */ d("div", { className: "flex items-center gap-2 border-t border-border p-4", children: [
|
|
95
|
-
/* @__PURE__ */ n(
|
|
96
|
-
p,
|
|
96
|
+
),
|
|
97
|
+
children: [
|
|
98
|
+
s,
|
|
99
|
+
/* @__PURE__ */ r(
|
|
100
|
+
M,
|
|
97
101
|
{
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
disabled: O,
|
|
101
|
-
onClick: w,
|
|
102
|
-
children: "Reset filters"
|
|
102
|
+
size: 16,
|
|
103
|
+
className: "transition-transform group-data-[popup-open]:rotate-180"
|
|
103
104
|
}
|
|
104
|
-
)
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
105
|
+
)
|
|
106
|
+
]
|
|
107
|
+
}
|
|
108
|
+
),
|
|
109
|
+
/* @__PURE__ */ r(
|
|
110
|
+
X,
|
|
111
|
+
{
|
|
112
|
+
side: o,
|
|
113
|
+
align: p,
|
|
114
|
+
sideOffset: w,
|
|
115
|
+
portalContainer: j,
|
|
116
|
+
collisionBoundary: O,
|
|
117
|
+
positionMethod: D,
|
|
118
|
+
className: u("w-96 p-0", S),
|
|
119
|
+
children: /* @__PURE__ */ d(
|
|
120
|
+
"form",
|
|
121
|
+
{
|
|
122
|
+
onSubmit: (a) => {
|
|
123
|
+
a.preventDefault(), B();
|
|
124
|
+
},
|
|
125
|
+
children: [
|
|
126
|
+
/* @__PURE__ */ r("div", { className: "flex max-h-80 flex-col gap-4 overflow-y-auto p-4", children: /* @__PURE__ */ r(R.Provider, { value: L, children: v }) }),
|
|
127
|
+
/* @__PURE__ */ d("div", { className: "flex items-center gap-2 border-t border-border p-4", children: [
|
|
128
|
+
/* @__PURE__ */ r(
|
|
129
|
+
h,
|
|
130
|
+
{
|
|
131
|
+
type: "button",
|
|
132
|
+
variant: "ghost",
|
|
133
|
+
disabled: I,
|
|
134
|
+
onClick: q,
|
|
135
|
+
children: b
|
|
136
|
+
}
|
|
137
|
+
),
|
|
138
|
+
/* @__PURE__ */ d("div", { className: "ms-auto flex items-center gap-2", children: [
|
|
139
|
+
/* @__PURE__ */ r(
|
|
140
|
+
h,
|
|
141
|
+
{
|
|
142
|
+
type: "button",
|
|
143
|
+
variant: "secondary",
|
|
144
|
+
onClick: z,
|
|
145
|
+
children: F
|
|
146
|
+
}
|
|
147
|
+
),
|
|
148
|
+
/* @__PURE__ */ r(
|
|
149
|
+
h,
|
|
150
|
+
{
|
|
151
|
+
type: "submit",
|
|
152
|
+
variant: "default",
|
|
153
|
+
disabled: J,
|
|
154
|
+
children: x
|
|
155
|
+
}
|
|
156
|
+
)
|
|
157
|
+
] })
|
|
158
|
+
] })
|
|
159
|
+
]
|
|
160
|
+
}
|
|
161
|
+
)
|
|
162
|
+
}
|
|
163
|
+
)
|
|
164
|
+
] });
|
|
165
|
+
}
|
|
166
|
+
);
|
|
167
|
+
_.displayName = "FilterSearchFilters";
|
|
168
|
+
function k(t, e) {
|
|
169
|
+
const n = Array.isArray(e) ? e.map((s) => String(s)).join(", ") : typeof e == "object" && e !== null ? JSON.stringify(e) : String(e);
|
|
170
|
+
return `${t}: ${n}`;
|
|
119
171
|
}
|
|
120
|
-
const
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
o
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
)
|
|
153
|
-
]
|
|
154
|
-
}
|
|
155
|
-
);
|
|
156
|
-
});
|
|
157
|
-
M.displayName = "FilterSearchAppliedFilters";
|
|
172
|
+
const V = i.forwardRef(
|
|
173
|
+
({
|
|
174
|
+
className: t,
|
|
175
|
+
filters: e,
|
|
176
|
+
onValueChange: n,
|
|
177
|
+
getFilterChipLabel: s,
|
|
178
|
+
getRemoveFilterLabel: b = (l) => `Remove ${l} filter`,
|
|
179
|
+
resetFiltersLabel: F = "Reset filters",
|
|
180
|
+
...x
|
|
181
|
+
}, v) => {
|
|
182
|
+
const l = Object.keys(e);
|
|
183
|
+
if (l.length === 0) return null;
|
|
184
|
+
const S = (o) => {
|
|
185
|
+
const p = { ...e };
|
|
186
|
+
delete p[o], n(p);
|
|
187
|
+
};
|
|
188
|
+
return /* @__PURE__ */ r(G, { ref: v, className: t, ...x, children: /* @__PURE__ */ d(H, { children: [
|
|
189
|
+
l.map((o) => /* @__PURE__ */ r(
|
|
190
|
+
Q,
|
|
191
|
+
{
|
|
192
|
+
variant: "removable",
|
|
193
|
+
onRemove: () => S(o),
|
|
194
|
+
removeLabel: b(o),
|
|
195
|
+
children: s ? s(o, e[o]) : k(o, e[o])
|
|
196
|
+
},
|
|
197
|
+
o
|
|
198
|
+
)),
|
|
199
|
+
/* @__PURE__ */ r(K, { onClick: () => n({}), children: F })
|
|
200
|
+
] }) });
|
|
201
|
+
}
|
|
202
|
+
);
|
|
203
|
+
V.displayName = "FilterSearchAppliedFilters";
|
|
158
204
|
export {
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
205
|
+
Y as FilterSearch,
|
|
206
|
+
Z as FilterSearchActions,
|
|
207
|
+
V as FilterSearchAppliedFilters,
|
|
208
|
+
_ as FilterSearchFilters,
|
|
209
|
+
le as useFilterSearchFilters
|
|
164
210
|
};
|
|
165
211
|
//# sourceMappingURL=filter-search.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"filter-search.js","sources":["../../../../src/components/ui/filter-search/filter-search.tsx"],"sourcesContent":["import * as React from 'react';\nimport { ChevronDownIcon } from '@acronis-platform/icons-react/stroke-mono';\n\nimport { cn } from '@/lib/utils';\nimport { deepEqual } from '@/lib/deep-equal';\nimport { Button } from '../button';\nimport { Chip } from '../chip';\nimport { Popover, PopoverContent, PopoverTrigger } from '../popover';\n\n// A composable toolbar for data tables: arranges a search field, optional\n// filters button, optional tenant/scope switcher, and trailing action buttons\n// in a single horizontal row. Maps to the Figma \"FilterSearch\" component. The\n// root container uses 16px inter-item gap (Figma `gap/gap-16`) and centers\n// children vertically. `FilterSearchActions` is a right-aligned flex area that\n// pushes its content to the trailing edge.\n//\n// No dedicated token tier — spacing is the Figma `gap/gap-16` semantic token\n// (16px), and each child (Search, ButtonMenu, Select) brings its own\n// `--ui-*` tier.\n//\n// `FilterSearchFilters` and `FilterSearchAppliedFilters` are design-pending\n// additions (no Figma node yet, unlike the FilterSearch node itself): the\n// filter popover (trigger + form + Reset/Cancel/Apply) and the applied-filter\n// chip row + top-level \"Reset filters\" affordance. Compose `FilterSearchFilters`\n// as a child of `<FilterSearch>` in place of a plain filter trigger, and render\n// `<FilterSearchAppliedFilters>` as a sibling row below it. Reconcile against\n// the real design with `/figma-component FilterSearchFilters <url> --update`\n// once a mockup lands.\n\nexport type FilterSearchProps = React.ComponentPropsWithoutRef<'div'>;\n\nconst FilterSearch = React.forwardRef<HTMLDivElement, FilterSearchProps>(\n ({ className, ...props }, ref) => (\n <div\n ref={ref}\n className={cn('flex items-center gap-4', className)}\n {...props}\n />\n )\n);\nFilterSearch.displayName = 'FilterSearch';\n\nexport type FilterSearchActionsProps = React.ComponentPropsWithoutRef<'div'>;\n\nconst FilterSearchActions = React.forwardRef<\n HTMLDivElement,\n FilterSearchActionsProps\n>(({ className, ...props }, ref) => (\n <div\n ref={ref}\n className={cn('flex h-8 min-w-px flex-1 items-center justify-end gap-4', className)}\n {...props}\n />\n));\nFilterSearchActions.displayName = 'FilterSearchActions';\n\ninterface FilterSearchFiltersContextValue {\n /** The current draft filters being edited inside the popover. */\n filters: Record<string, unknown>;\n /** Set a single draft filter value by key. */\n setFilter: (key: string, value: unknown) => void;\n}\n\nconst FilterSearchFiltersContext =\n React.createContext<FilterSearchFiltersContextValue | null>(null);\n\n/**\n * Bind a filter field child (rendered inside `FilterSearchFilters`'s popover) to\n * the component's draft filters. Returns the current draft map and a per-key\n * setter. Field children are plain JSX (no render prop) and wire their own\n * `onChange` to `setFilter`; Apply commits the draft, Cancel/dismiss reverts it.\n */\nexport function useFilterSearchFilters(): FilterSearchFiltersContextValue {\n const context = React.useContext(FilterSearchFiltersContext);\n if (context === null) {\n throw new Error(\n 'useFilterSearchFilters must be used within a <FilterSearchFilters> popover.'\n );\n }\n return context;\n}\n\nexport interface FilterSearchFiltersProps\n extends Omit<React.ComponentPropsWithoutRef<'button'>, 'value' | 'onValueChange'> {\n /** The applied filter values, keyed by an arbitrary consumer-chosen id. */\n value: Record<string, unknown>;\n /** Called with the committed filters when Apply is pressed. */\n onValueChange: (next: Record<string, unknown>) => void;\n /** Called with the newly applied filters when Apply is pressed (fires alongside `onValueChange`). */\n onApply?: (filters: Record<string, unknown>) => void;\n /** Label for the filter trigger button. */\n label?: React.ReactNode;\n /**\n * Filter field children rendered inside the popover form. Plain children —\n * wire each field to the draft via `useFilterSearchFilters`. Group fields with\n * a `Separator` as a layout convention if desired.\n */\n children?: React.ReactNode;\n /** Additional classes merged onto the trigger button. */\n className?: string;\n}\n\nconst FilterSearchFilters = React.forwardRef<\n HTMLButtonElement,\n FilterSearchFiltersProps\n>(({ value, onValueChange, onApply, label = 'Filters', children, className, ...rest }, ref) => {\n const [open, setOpen] = React.useState(false);\n const [draft, setDraft] = React.useState<Record<string, unknown>>(value);\n\n const handleOpenChange = (nextOpen: boolean) => {\n // Snapshot the applied filters on open; revert the draft on any dismiss\n // (outside press / Escape) so an un-applied edit never leaks out.\n setDraft(value);\n setOpen(nextOpen);\n };\n\n const setFilter = React.useCallback((key: string, filterValue: unknown) => {\n setDraft((previous) => {\n if (filterValue === undefined) {\n if (!(key in previous)) return previous;\n const next = { ...previous };\n delete next[key];\n return next;\n }\n return { ...previous, [key]: filterValue };\n });\n }, []);\n\n const filterContext = React.useMemo<FilterSearchFiltersContextValue>(\n () => ({ filters: draft, setFilter }),\n [draft, setFilter]\n );\n\n const handleReset = () => setDraft({});\n\n const handleCancel = () => {\n setDraft(value);\n setOpen(false);\n };\n\n const handleApply = () => {\n onValueChange(draft);\n onApply?.(draft);\n setOpen(false);\n };\n\n const resetDisabled = Object.keys(draft).length === 0;\n const applyDisabled = deepEqual(draft, value);\n\n return (\n <Popover open={open} onOpenChange={handleOpenChange}>\n <PopoverTrigger\n ref={ref}\n render={\n <Button\n variant=\"secondary\"\n className={cn(\n 'group data-[popup-open]:border-[var(--ui-button-secondary-container-border-color-active)] data-[popup-open]:bg-[var(--ui-button-secondary-container-color-active)] data-[popup-open]:text-[var(--ui-button-secondary-label-color-active)]',\n className\n )}\n {...rest}\n />\n }\n >\n {label}\n <ChevronDownIcon\n size={16}\n className=\"transition-transform group-data-[popup-open]:rotate-180\"\n />\n </PopoverTrigger>\n <PopoverContent align=\"start\" className=\"w-96 p-0\">\n <form\n onSubmit={(event) => {\n event.preventDefault();\n handleApply();\n }}\n >\n <div className=\"flex max-h-80 flex-col gap-4 overflow-y-auto p-4\">\n <FilterSearchFiltersContext.Provider value={filterContext}>\n {children}\n </FilterSearchFiltersContext.Provider>\n </div>\n <div className=\"flex items-center gap-2 border-t border-border p-4\">\n <Button\n type=\"button\"\n variant=\"ghost\"\n disabled={resetDisabled}\n onClick={handleReset}\n >\n Reset filters\n </Button>\n <div className=\"ms-auto flex items-center gap-2\">\n <Button type=\"button\" variant=\"secondary\" onClick={handleCancel}>\n Cancel\n </Button>\n <Button type=\"submit\" variant=\"default\" disabled={applyDisabled}>\n Apply\n </Button>\n </div>\n </div>\n </form>\n </PopoverContent>\n </Popover>\n );\n});\nFilterSearchFilters.displayName = 'FilterSearchFilters';\n\nfunction defaultFilterChipLabel(key: string, value: unknown): string {\n const text = Array.isArray(value)\n ? value.map((entry) => String(entry)).join(', ')\n : typeof value === 'object' && value !== null\n ? JSON.stringify(value)\n : String(value);\n return `${key}: ${text}`;\n}\n\nexport interface FilterSearchAppliedFiltersProps\n extends Omit<React.ComponentPropsWithoutRef<'div'>, 'children'> {\n /** The currently applied filter values, keyed by an arbitrary consumer-chosen id. */\n filters: Record<string, unknown>;\n /** Called with the remaining filters when a chip is removed or \"Reset filters\" clears all. */\n onValueChange: (next: Record<string, unknown>) => void;\n /** Format an applied-filter chip's label. Defaults to `\"<key>: <value>\"`. */\n getFilterChipLabel?: (key: string, value: unknown) => React.ReactNode;\n}\n\n/**\n * Renders one removable chip per applied filter plus a \"Reset filters\" action\n * that clears all filters immediately (no popover involved). Renders nothing\n * when `filters` is empty.\n */\nconst FilterSearchAppliedFilters = React.forwardRef<\n HTMLDivElement,\n FilterSearchAppliedFiltersProps\n>(({ className, filters, onValueChange, getFilterChipLabel, ...props }, ref) => {\n const keys = Object.keys(filters);\n if (keys.length === 0) return null;\n\n const handleRemove = (key: string) => {\n const next = { ...filters };\n delete next[key];\n onValueChange(next);\n };\n\n return (\n <div\n ref={ref}\n className={cn('flex flex-wrap items-center gap-3', className)}\n {...props}\n >\n {keys.map((key) => (\n <Chip\n key={key}\n variant=\"removable\"\n onRemove={() => handleRemove(key)}\n removeLabel={`Remove ${key} filter`}\n >\n {getFilterChipLabel\n ? getFilterChipLabel(key, filters[key])\n : defaultFilterChipLabel(key, filters[key])}\n </Chip>\n ))}\n <Button\n type=\"button\"\n variant=\"ghost\"\n onClick={() => onValueChange({})}\n >\n Reset filters\n </Button>\n </div>\n );\n});\nFilterSearchAppliedFilters.displayName = 'FilterSearchAppliedFilters';\n\nexport {\n FilterSearch,\n FilterSearchActions,\n FilterSearchFilters,\n FilterSearchAppliedFilters,\n};\n"],"names":["FilterSearch","React","className","props","ref","jsx","cn","FilterSearchActions","FilterSearchFiltersContext","useFilterSearchFilters","context","FilterSearchFilters","value","onValueChange","onApply","label","children","rest","open","setOpen","draft","setDraft","handleOpenChange","nextOpen","setFilter","key","filterValue","previous","next","filterContext","handleReset","handleCancel","handleApply","resetDisabled","applyDisabled","deepEqual","jsxs","Popover","PopoverTrigger","Button","ChevronDownIcon","PopoverContent","event","defaultFilterChipLabel","text","entry","FilterSearchAppliedFilters","filters","getFilterChipLabel","keys","handleRemove","Chip"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"filter-search.js","sources":["../../../../src/components/ui/filter-search/filter-search.tsx"],"sourcesContent":["import * as React from 'react';\nimport { ChevronDownIcon } from '@acronis-platform/icons-react/stroke-mono';\n\nimport { cn } from '@/lib/utils';\nimport { deepEqual } from '@/lib/deep-equal';\nimport { Button } from '../button';\nimport { Chip } from '../chip';\nimport {\n FilterChips,\n FilterChipsList,\n FilterChipsReset,\n type FilterChipsProps,\n} from '../filter-chips';\nimport { Popover, PopoverContent, PopoverTrigger } from '../popover';\n\n// A composable toolbar for data tables: arranges a search field, optional\n// filters button, optional tenant/scope switcher, and trailing action buttons\n// in a single horizontal row. Maps to the Figma \"FilterSearch\" component. The\n// root container uses 16px inter-item gap (Figma `gap/gap-16`) and centers\n// children vertically. `FilterSearchActions` is a right-aligned flex area that\n// pushes its content to the trailing edge.\n//\n// No dedicated token tier — spacing is the Figma `gap/gap-16` semantic token\n// (16px), and each child (Search, ButtonMenu, Select) brings its own\n// `--ui-*` tier.\n//\n// `FilterSearchFilters` is still design-pending (no Figma node yet, unlike the\n// FilterSearch node itself): the filter popover — trigger + form +\n// Reset/Cancel/Apply. Compose it as a child of `<FilterSearch>` in place of a\n// plain filter trigger, and reconcile against the real design with\n// `/figma-component FilterSearchFilters <url> --update` once a mockup lands.\n//\n// `FilterSearchAppliedFilters` is no longer design-pending: its chip row landed\n// in Figma as its own \"FilterChips\" component, so it renders through\n// `FilterChips`/`FilterChipsList`/`FilterChipsReset` rather than repeating that\n// layout. It keeps its data-driven API (a `filters` record) as the convenience\n// wrapper over those slot-based parts; render it as a sibling row below\n// `<FilterSearch>`.\n\nexport type FilterSearchProps = React.ComponentPropsWithoutRef<'div'>;\n\nconst FilterSearch = React.forwardRef<HTMLDivElement, FilterSearchProps>(\n ({ className, ...props }, ref) => (\n <div\n ref={ref}\n className={cn('flex items-center gap-4', className)}\n {...props}\n />\n )\n);\nFilterSearch.displayName = 'FilterSearch';\n\nexport type FilterSearchActionsProps = React.ComponentPropsWithoutRef<'div'>;\n\nconst FilterSearchActions = React.forwardRef<\n HTMLDivElement,\n FilterSearchActionsProps\n>(({ className, ...props }, ref) => (\n <div\n ref={ref}\n className={cn(\n 'flex h-8 min-w-px flex-1 items-center justify-end gap-4',\n className\n )}\n {...props}\n />\n));\nFilterSearchActions.displayName = 'FilterSearchActions';\n\ninterface FilterSearchFiltersContextValue {\n /** The current draft filters being edited inside the popover. */\n filters: Record<string, unknown>;\n /** Set a single draft filter value by key. */\n setFilter: (key: string, value: unknown) => void;\n}\n\nconst FilterSearchFiltersContext =\n React.createContext<FilterSearchFiltersContextValue | null>(null);\n\n/**\n * Bind a filter field child (rendered inside `FilterSearchFilters`'s popover) to\n * the component's draft filters. Returns the current draft map and a per-key\n * setter. Field children are plain JSX (no render prop) and wire their own\n * `onChange` to `setFilter`; Apply commits the draft, Cancel/dismiss reverts it.\n */\nexport function useFilterSearchFilters(): FilterSearchFiltersContextValue {\n const context = React.useContext(FilterSearchFiltersContext);\n if (context === null) {\n throw new Error(\n 'useFilterSearchFilters must be used within a <FilterSearchFilters> popover.'\n );\n }\n return context;\n}\n\nexport interface FilterSearchFiltersProps extends Omit<\n React.ComponentPropsWithoutRef<'button'>,\n 'value' | 'onValueChange'\n> {\n /** The applied filter values, keyed by an arbitrary consumer-chosen id. */\n value: Record<string, unknown>;\n /** Called with the committed filters when Apply is pressed. */\n onValueChange: (next: Record<string, unknown>) => void;\n /** Called with the newly applied filters when Apply is pressed (fires alongside `onValueChange`). */\n onApply?: (filters: Record<string, unknown>) => void;\n /** Label for the filter trigger button. */\n label?: React.ReactNode;\n /** Label for the \"Reset filters\" action inside the popover. */\n resetFiltersLabel?: React.ReactNode;\n /** Label for the \"Cancel\" action inside the popover. */\n cancelLabel?: React.ReactNode;\n /** Label for the \"Apply\" action inside the popover. */\n applyLabel?: React.ReactNode;\n /**\n * Filter field children rendered inside the popover form. Plain children —\n * wire each field to the draft via `useFilterSearchFilters`. Group fields with\n * a `Separator` as a layout convention if desired.\n */\n children?: React.ReactNode;\n /** Additional classes merged onto the trigger button. */\n className?: string;\n /** Additional classes merged onto the popover content. */\n contentClassName?: string;\n /** Which side of the trigger to render the popover on. Defaults to `'bottom'`. */\n side?: React.ComponentProps<typeof PopoverContent>['side'];\n /** Alignment of the popover along the chosen side. Defaults to `'start'`. */\n align?: React.ComponentProps<typeof PopoverContent>['align'];\n /** Distance in px between the trigger and the popover. */\n sideOffset?: React.ComponentProps<typeof PopoverContent>['sideOffset'];\n /**\n * Portal container the popover mounts into. Defaults to the nearest\n * `PortalContainerProvider`, or `document.body` if none is set — see\n * `PopoverContent`'s `portalContainer` prop.\n */\n portalContainer?: React.ComponentProps<\n typeof PopoverContent\n >['portalContainer'];\n /**\n * Element/rect the popover is confined to when avoiding collisions. See\n * `PopoverContent`'s `collisionBoundary` prop for the default behavior\n * inside a constrained portal container.\n */\n collisionBoundary?: React.ComponentProps<\n typeof PopoverContent\n >['collisionBoundary'];\n /**\n * Which CSS `position` the popover uses. See `PopoverContent`'s\n * `positionMethod` prop for the default behavior inside a constrained\n * portal container.\n */\n positionMethod?: React.ComponentProps<\n typeof PopoverContent\n >['positionMethod'];\n}\n\nconst FilterSearchFilters = React.forwardRef<\n HTMLButtonElement,\n FilterSearchFiltersProps\n>(\n (\n {\n value,\n onValueChange,\n onApply,\n label = 'Filters',\n resetFiltersLabel = 'Reset filters',\n cancelLabel = 'Cancel',\n applyLabel = 'Apply',\n children,\n className,\n contentClassName,\n side,\n align = 'start',\n sideOffset,\n portalContainer,\n collisionBoundary,\n positionMethod,\n ...rest\n },\n ref\n ) => {\n const [open, setOpen] = React.useState(false);\n const [draft, setDraft] = React.useState<Record<string, unknown>>(value);\n\n const handleOpenChange = (nextOpen: boolean) => {\n // Snapshot the applied filters on open; revert the draft on any dismiss\n // (outside press / Escape) so an un-applied edit never leaks out.\n setDraft(value);\n setOpen(nextOpen);\n };\n\n const setFilter = React.useCallback((key: string, filterValue: unknown) => {\n setDraft((previous) => {\n if (filterValue === undefined) {\n if (!(key in previous)) return previous;\n const next = { ...previous };\n delete next[key];\n return next;\n }\n return { ...previous, [key]: filterValue };\n });\n }, []);\n\n const filterContext = React.useMemo<FilterSearchFiltersContextValue>(\n () => ({ filters: draft, setFilter }),\n [draft, setFilter]\n );\n\n const handleReset = () => setDraft({});\n\n const handleCancel = () => {\n setDraft(value);\n setOpen(false);\n };\n\n const handleApply = () => {\n onValueChange(draft);\n onApply?.(draft);\n setOpen(false);\n };\n\n const resetDisabled = Object.keys(draft).length === 0;\n const applyDisabled = deepEqual(draft, value);\n\n return (\n <Popover open={open} onOpenChange={handleOpenChange}>\n <PopoverTrigger\n ref={ref}\n render={\n <Button\n variant=\"secondary\"\n className={cn(\n 'group data-[popup-open]:border-[var(--ui-button-secondary-container-border-color-active)] data-[popup-open]:bg-[var(--ui-button-secondary-container-color-active)] data-[popup-open]:text-[var(--ui-button-secondary-label-color-active)]',\n className\n )}\n {...rest}\n />\n }\n >\n {label}\n <ChevronDownIcon\n size={16}\n className=\"transition-transform group-data-[popup-open]:rotate-180\"\n />\n </PopoverTrigger>\n <PopoverContent\n side={side}\n align={align}\n sideOffset={sideOffset}\n portalContainer={portalContainer}\n collisionBoundary={collisionBoundary}\n positionMethod={positionMethod}\n className={cn('w-96 p-0', contentClassName)}\n >\n <form\n onSubmit={(event) => {\n event.preventDefault();\n handleApply();\n }}\n >\n <div className=\"flex max-h-80 flex-col gap-4 overflow-y-auto p-4\">\n <FilterSearchFiltersContext.Provider value={filterContext}>\n {children}\n </FilterSearchFiltersContext.Provider>\n </div>\n <div className=\"flex items-center gap-2 border-t border-border p-4\">\n <Button\n type=\"button\"\n variant=\"ghost\"\n disabled={resetDisabled}\n onClick={handleReset}\n >\n {resetFiltersLabel}\n </Button>\n <div className=\"ms-auto flex items-center gap-2\">\n <Button\n type=\"button\"\n variant=\"secondary\"\n onClick={handleCancel}\n >\n {cancelLabel}\n </Button>\n <Button\n type=\"submit\"\n variant=\"default\"\n disabled={applyDisabled}\n >\n {applyLabel}\n </Button>\n </div>\n </div>\n </form>\n </PopoverContent>\n </Popover>\n );\n }\n);\nFilterSearchFilters.displayName = 'FilterSearchFilters';\n\nfunction defaultFilterChipLabel(key: string, value: unknown): string {\n const text = Array.isArray(value)\n ? value.map((entry) => String(entry)).join(', ')\n : typeof value === 'object' && value !== null\n ? JSON.stringify(value)\n : String(value);\n return `${key}: ${text}`;\n}\n\nexport interface FilterSearchAppliedFiltersProps\n extends Omit<FilterChipsProps, 'children'> {\n /** The currently applied filter values, keyed by an arbitrary consumer-chosen id. */\n filters: Record<string, unknown>;\n /** Called with the remaining filters when a chip is removed or \"Reset filters\" clears all. */\n onValueChange: (next: Record<string, unknown>) => void;\n /** Format an applied-filter chip's label. Defaults to `\"<key>: <value>\"`. */\n getFilterChipLabel?: (key: string, value: unknown) => React.ReactNode;\n /** Format a filter chip's remove-button accessible label. Defaults to `\"Remove <key> filter\"`. */\n getRemoveFilterLabel?: (key: string) => string;\n /** Label for the \"Reset filters\" action. */\n resetFiltersLabel?: React.ReactNode;\n}\n\n/**\n * Renders one removable chip per applied filter plus a \"Reset filters\" action\n * that clears all filters immediately (no popover involved). Renders nothing\n * when `filters` is empty.\n */\nconst FilterSearchAppliedFilters = React.forwardRef<\n HTMLDivElement,\n FilterSearchAppliedFiltersProps\n>(\n (\n {\n className,\n filters,\n onValueChange,\n getFilterChipLabel,\n getRemoveFilterLabel = (key) => `Remove ${key} filter`,\n resetFiltersLabel = 'Reset filters',\n ...props\n },\n ref\n ) => {\n const keys = Object.keys(filters);\n if (keys.length === 0) return null;\n\n const handleRemove = (key: string) => {\n const next = { ...filters };\n delete next[key];\n onValueChange(next);\n };\n\n return (\n <FilterChips ref={ref} className={className} {...props}>\n <FilterChipsList>\n {keys.map((key) => (\n <Chip\n key={key}\n variant=\"removable\"\n onRemove={() => handleRemove(key)}\n removeLabel={getRemoveFilterLabel(key)}\n >\n {getFilterChipLabel\n ? getFilterChipLabel(key, filters[key])\n : defaultFilterChipLabel(key, filters[key])}\n </Chip>\n ))}\n <FilterChipsReset onClick={() => onValueChange({})}>\n {resetFiltersLabel}\n </FilterChipsReset>\n </FilterChipsList>\n </FilterChips>\n );\n }\n);\nFilterSearchAppliedFilters.displayName = 'FilterSearchAppliedFilters';\n\nexport {\n FilterSearch,\n FilterSearchActions,\n FilterSearchFilters,\n FilterSearchAppliedFilters,\n};\n"],"names":["FilterSearch","React","className","props","ref","jsx","cn","FilterSearchActions","FilterSearchFiltersContext","useFilterSearchFilters","context","FilterSearchFilters","value","onValueChange","onApply","label","resetFiltersLabel","cancelLabel","applyLabel","children","contentClassName","side","align","sideOffset","portalContainer","collisionBoundary","positionMethod","rest","open","setOpen","draft","setDraft","handleOpenChange","nextOpen","setFilter","key","filterValue","previous","next","filterContext","handleReset","handleCancel","handleApply","resetDisabled","applyDisabled","deepEqual","jsxs","Popover","PopoverTrigger","Button","ChevronDownIcon","PopoverContent","event","defaultFilterChipLabel","text","entry","FilterSearchAppliedFilters","filters","getFilterChipLabel","getRemoveFilterLabel","keys","handleRemove","FilterChips","FilterChipsList","Chip","FilterChipsReset"],"mappings":"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"}
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
import { jsx as p, jsxs as l, Fragment as G } from "react/jsx-runtime";
|
|
2
|
+
import * as s from "react";
|
|
3
|
+
import { cn as k } from "../../../lib/utils.js";
|
|
4
|
+
import { Button as V, buttonVariants as I } from "../button/button.js";
|
|
5
|
+
import { DropdownMenu as P, DropdownMenuTrigger as T, DropdownMenuContent as U, DropdownMenuItem as _ } from "../dropdown-menu/dropdown-menu.js";
|
|
6
|
+
const D = 8;
|
|
7
|
+
function q({
|
|
8
|
+
containerWidth: m,
|
|
9
|
+
itemWidths: n,
|
|
10
|
+
dropdownWidth: d,
|
|
11
|
+
gap: r = D
|
|
12
|
+
}) {
|
|
13
|
+
const i = n.length;
|
|
14
|
+
if (i === 0) return 0;
|
|
15
|
+
const b = m - d;
|
|
16
|
+
let o = 0, c = 0;
|
|
17
|
+
for (let u = 0; u < i; u += 1) {
|
|
18
|
+
const h = o + (c > 0 ? r : 0) + (n[u] ?? 0);
|
|
19
|
+
if (h <= b)
|
|
20
|
+
o = h, c += 1;
|
|
21
|
+
else break;
|
|
22
|
+
}
|
|
23
|
+
return c;
|
|
24
|
+
}
|
|
25
|
+
const w = I({ variant: "ghost" }), H = s.forwardRef(
|
|
26
|
+
({
|
|
27
|
+
actions: m = [],
|
|
28
|
+
showDropdown: n = !0,
|
|
29
|
+
moreLabel: d = "More",
|
|
30
|
+
gap: r = D,
|
|
31
|
+
onAction: i,
|
|
32
|
+
renderAction: b,
|
|
33
|
+
renderTrigger: o,
|
|
34
|
+
className: c,
|
|
35
|
+
style: u,
|
|
36
|
+
...h
|
|
37
|
+
}, a) => {
|
|
38
|
+
const t = s.useMemo(
|
|
39
|
+
() => m.filter((e) => e.isDisplayed !== !1),
|
|
40
|
+
[m]
|
|
41
|
+
), x = s.useRef(null), y = s.useRef(null), [E, S] = s.useState(t.length), j = s.useCallback(
|
|
42
|
+
(e) => {
|
|
43
|
+
x.current = e, typeof a == "function" ? a(e) : a && (a.current = e);
|
|
44
|
+
},
|
|
45
|
+
[a]
|
|
46
|
+
);
|
|
47
|
+
s.useLayoutEffect(() => {
|
|
48
|
+
const e = x.current, f = y.current;
|
|
49
|
+
if (!n || !e || !f || typeof ResizeObserver > "u")
|
|
50
|
+
return;
|
|
51
|
+
const N = new ResizeObserver(() => {
|
|
52
|
+
var W;
|
|
53
|
+
const g = Array.from(f.children), $ = ((W = g[g.length - 1]) == null ? void 0 : W.offsetWidth) ?? 0, A = g.slice(0, t.length).map((B) => B.offsetWidth), R = e.clientWidth;
|
|
54
|
+
S(
|
|
55
|
+
R === 0 ? t.length : q({
|
|
56
|
+
containerWidth: R,
|
|
57
|
+
itemWidths: A,
|
|
58
|
+
dropdownWidth: $,
|
|
59
|
+
gap: r
|
|
60
|
+
})
|
|
61
|
+
);
|
|
62
|
+
});
|
|
63
|
+
return N.observe(e), () => N.disconnect();
|
|
64
|
+
}, [t, n, d, r]);
|
|
65
|
+
const C = n ? E : t.length, z = t.slice(0, C), F = n ? t.slice(C) : [], v = (e) => {
|
|
66
|
+
var f;
|
|
67
|
+
(f = e.onSelect) == null || f.call(e), i == null || i(e);
|
|
68
|
+
}, O = (e) => /* @__PURE__ */ l(
|
|
69
|
+
V,
|
|
70
|
+
{
|
|
71
|
+
variant: "ghost",
|
|
72
|
+
disabled: e.disabled,
|
|
73
|
+
onClick: () => v(e),
|
|
74
|
+
children: [
|
|
75
|
+
e.icon,
|
|
76
|
+
e.label
|
|
77
|
+
]
|
|
78
|
+
}
|
|
79
|
+
), M = o ? o({ label: d }) : /* @__PURE__ */ p(V, { variant: "ghost", children: d });
|
|
80
|
+
return /* @__PURE__ */ l(G, { children: [
|
|
81
|
+
/* @__PURE__ */ l(
|
|
82
|
+
"div",
|
|
83
|
+
{
|
|
84
|
+
ref: j,
|
|
85
|
+
"data-slot": "fitted-actions",
|
|
86
|
+
className: k("flex min-w-0 items-center overflow-hidden", c),
|
|
87
|
+
style: { gap: `${r}px`, ...u },
|
|
88
|
+
...h,
|
|
89
|
+
children: [
|
|
90
|
+
z.map((e) => /* @__PURE__ */ p(s.Fragment, { children: b ? b(e, {
|
|
91
|
+
onSelect: () => v(e),
|
|
92
|
+
disabled: e.disabled
|
|
93
|
+
}) : O(e) }, e.id)),
|
|
94
|
+
F.length > 0 && /* @__PURE__ */ l(P, { children: [
|
|
95
|
+
/* @__PURE__ */ p(T, { render: M }),
|
|
96
|
+
/* @__PURE__ */ p(U, { align: "end", children: F.map((e) => /* @__PURE__ */ l(
|
|
97
|
+
_,
|
|
98
|
+
{
|
|
99
|
+
disabled: e.disabled,
|
|
100
|
+
onClick: () => v(e),
|
|
101
|
+
className: k(
|
|
102
|
+
e.divided && "mt-1 border-t border-border pt-1"
|
|
103
|
+
),
|
|
104
|
+
children: [
|
|
105
|
+
e.icon,
|
|
106
|
+
e.label
|
|
107
|
+
]
|
|
108
|
+
},
|
|
109
|
+
e.id
|
|
110
|
+
)) })
|
|
111
|
+
] })
|
|
112
|
+
]
|
|
113
|
+
}
|
|
114
|
+
),
|
|
115
|
+
/* @__PURE__ */ l(
|
|
116
|
+
"div",
|
|
117
|
+
{
|
|
118
|
+
ref: y,
|
|
119
|
+
"aria-hidden": "true",
|
|
120
|
+
className: "pointer-events-none invisible absolute left-0 top-0 flex",
|
|
121
|
+
style: { gap: `${r}px` },
|
|
122
|
+
children: [
|
|
123
|
+
t.map((e) => /* @__PURE__ */ l("span", { className: w, children: [
|
|
124
|
+
e.icon,
|
|
125
|
+
e.label
|
|
126
|
+
] }, e.id)),
|
|
127
|
+
M
|
|
128
|
+
]
|
|
129
|
+
}
|
|
130
|
+
)
|
|
131
|
+
] });
|
|
132
|
+
}
|
|
133
|
+
);
|
|
134
|
+
H.displayName = "FittedActions";
|
|
135
|
+
export {
|
|
136
|
+
H as FittedActions,
|
|
137
|
+
q as computeFittedVisibleCount
|
|
138
|
+
};
|
|
139
|
+
//# sourceMappingURL=fitted-actions.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fitted-actions.js","sources":["../../../../src/components/ui/fitted-actions/fitted-actions.tsx"],"sourcesContent":["import * as React from 'react';\n\nimport { cn } from '@/lib/utils';\nimport { Button, buttonVariants } from '../button';\nimport {\n DropdownMenu,\n DropdownMenuContent,\n DropdownMenuItem,\n DropdownMenuTrigger,\n} from '../dropdown-menu';\n\n// A responsive action row with automatic overflow — actions render inline in\n// priority order; when they don't fit the available width, the trailing ones\n// collapse into a \"More\" dropdown menu, recomputed on resize (ResizeObserver).\n//\n// Widths come from an off-screen \"tracing layer\" that renders every action at its\n// intrinsic width (ghost-button footprint) plus the overflow trigger; the pure\n// `computeFittedVisibleCount` turns those measurements into a visible count. All\n// state updates happen inside the ResizeObserver callback (never synchronously in\n// the effect), so before the first measurement every action is shown.\n\nconst DEFAULT_GAP = 8;\n\n/**\n * Pure overflow math (no DOM). Greedily fits leading actions into\n * `containerWidth - dropdownWidth`, accounting for the inter-item `gap`. Returns\n * how many render inline; the rest overflow into the menu. Exported for testing.\n */\nexport function computeFittedVisibleCount({\n containerWidth,\n itemWidths,\n dropdownWidth,\n gap = DEFAULT_GAP,\n}: {\n containerWidth: number;\n itemWidths: number[];\n dropdownWidth: number;\n gap?: number;\n}): number {\n const count = itemWidths.length;\n if (count === 0) return 0;\n const available = containerWidth - dropdownWidth;\n let used = 0;\n let visible = 0;\n for (let index = 0; index < count; index += 1) {\n const next = used + (visible > 0 ? gap : 0) + (itemWidths[index] ?? 0);\n if (next <= available) {\n used = next;\n visible += 1;\n } else break;\n }\n return visible;\n}\n\nexport interface FittedAction {\n /** Stable identity. */\n id: string;\n /** Visible label (also the overflow menu-item label). */\n label: React.ReactNode;\n /** Optional leading 16px icon. */\n icon?: React.ReactNode;\n /** Set `false` to omit the action entirely. */\n isDisplayed?: boolean;\n /** Render a divider above this item when it sits in the overflow menu. */\n divided?: boolean;\n disabled?: boolean;\n /** Invoked when this action is chosen (inline click or menu select). */\n onSelect?: () => void;\n}\n\nexport interface FittedActionsProps\n extends Omit<React.HTMLAttributes<HTMLDivElement>, 'onSelect'> {\n /** Ordered actions; trailing items overflow into the menu first. Defaults to `[]`. */\n actions?: FittedAction[];\n /** Collapse overflow into a \"More\" menu. Default true. */\n showDropdown?: boolean;\n /** Label for the overflow trigger. Default \"More\". */\n moreLabel?: React.ReactNode;\n /** Inter-item gap in px (also reserved when measuring). Default 8. */\n gap?: number;\n /** Fired for any chosen action, after its own `onSelect`. */\n onAction?: (action: FittedAction) => void;\n /** Customize the inline action element. Default: a ghost `Button`. */\n renderAction?: (\n action: FittedAction,\n api: { onSelect: () => void; disabled?: boolean }\n ) => React.ReactNode;\n /** Customize the overflow trigger (used as the menu trigger's `render`). Default: a ghost `Button`. */\n renderTrigger?: (api: { label: React.ReactNode }) => React.ReactElement;\n}\n\nconst measureClass = buttonVariants({ variant: 'ghost' });\n\nconst FittedActions = React.forwardRef<HTMLDivElement, FittedActionsProps>(\n (\n {\n actions = [],\n showDropdown = true,\n moreLabel = 'More',\n gap = DEFAULT_GAP,\n onAction,\n renderAction,\n renderTrigger,\n className,\n style,\n ...props\n },\n forwardedRef\n ) => {\n const displayed = React.useMemo(\n () => actions.filter((action) => action.isDisplayed !== false),\n [actions]\n );\n\n const containerRef = React.useRef<HTMLDivElement | null>(null);\n const measureRef = React.useRef<HTMLDivElement | null>(null);\n const [visibleCount, setVisibleCount] = React.useState(displayed.length);\n\n const setContainer = React.useCallback(\n (node: HTMLDivElement | null) => {\n containerRef.current = node;\n if (typeof forwardedRef === 'function') forwardedRef(node);\n else if (forwardedRef) forwardedRef.current = node;\n },\n [forwardedRef]\n );\n\n React.useLayoutEffect(() => {\n const container = containerRef.current;\n const measure = measureRef.current;\n // With no overflow menu, or no way to measure, show everything inline.\n // Every state update happens inside the observer callback below (which\n // fires an initial notification on observe), never synchronously here.\n if (\n !showDropdown ||\n !container ||\n !measure ||\n typeof ResizeObserver === 'undefined'\n )\n return;\n const observer = new ResizeObserver(() => {\n const clones = Array.from(measure.children) as HTMLElement[];\n const dropdownWidth = clones[clones.length - 1]?.offsetWidth ?? 0;\n const itemWidths = clones\n .slice(0, displayed.length)\n .map((element) => element.offsetWidth);\n const containerWidth = container.clientWidth;\n setVisibleCount(\n containerWidth === 0\n ? displayed.length\n : computeFittedVisibleCount({\n containerWidth,\n itemWidths,\n dropdownWidth,\n gap,\n })\n );\n });\n observer.observe(container);\n return () => observer.disconnect();\n }, [displayed, showDropdown, moreLabel, gap]);\n\n const effectiveVisible = showDropdown ? visibleCount : displayed.length;\n const inline = displayed.slice(0, effectiveVisible);\n const overflow = showDropdown ? displayed.slice(effectiveVisible) : [];\n\n const select = (action: FittedAction) => {\n action.onSelect?.();\n onAction?.(action);\n };\n\n const defaultRenderAction = (action: FittedAction) => (\n <Button\n variant=\"ghost\"\n disabled={action.disabled}\n onClick={() => select(action)}\n >\n {action.icon}\n {action.label}\n </Button>\n );\n\n const triggerElement = renderTrigger ? (\n renderTrigger({ label: moreLabel })\n ) : (\n <Button variant=\"ghost\">{moreLabel}</Button>\n );\n\n return (\n <>\n <div\n ref={setContainer}\n data-slot=\"fitted-actions\"\n className={cn('flex min-w-0 items-center overflow-hidden', className)}\n style={{ gap: `${gap}px`, ...style }}\n {...props}\n >\n {inline.map((action) => (\n <React.Fragment key={action.id}>\n {renderAction\n ? renderAction(action, {\n onSelect: () => select(action),\n disabled: action.disabled,\n })\n : defaultRenderAction(action)}\n </React.Fragment>\n ))}\n {overflow.length > 0 && (\n <DropdownMenu>\n <DropdownMenuTrigger render={triggerElement} />\n <DropdownMenuContent align=\"end\">\n {overflow.map((action) => (\n <DropdownMenuItem\n key={action.id}\n disabled={action.disabled}\n onClick={() => select(action)}\n className={cn(\n action.divided && 'mt-1 border-t border-border pt-1'\n )}\n >\n {action.icon}\n {action.label}\n </DropdownMenuItem>\n ))}\n </DropdownMenuContent>\n </DropdownMenu>\n )}\n </div>\n {/* Off-screen tracing layer: intrinsic widths of every action (ghost\n footprint) + the overflow trigger, read on resize. Not part of the\n focus order or the a11y tree. */}\n <div\n ref={measureRef}\n aria-hidden=\"true\"\n className=\"pointer-events-none invisible absolute left-0 top-0 flex\"\n style={{ gap: `${gap}px` }}\n >\n {displayed.map((action) => (\n <span key={action.id} className={measureClass}>\n {action.icon}\n {action.label}\n </span>\n ))}\n {triggerElement}\n </div>\n </>\n );\n }\n);\nFittedActions.displayName = 'FittedActions';\n\nexport { FittedActions };\n"],"names":["DEFAULT_GAP","computeFittedVisibleCount","containerWidth","itemWidths","dropdownWidth","gap","count","available","used","visible","index","next","measureClass","buttonVariants","FittedActions","React","actions","showDropdown","moreLabel","onAction","renderAction","renderTrigger","className","style","props","forwardedRef","displayed","action","containerRef","measureRef","visibleCount","setVisibleCount","setContainer","node","container","measure","observer","clones","_a","element","effectiveVisible","inline","overflow","select","defaultRenderAction","jsxs","Button","triggerElement","jsx","Fragment","cn","DropdownMenu","DropdownMenuTrigger","DropdownMenuContent","DropdownMenuItem"],"mappings":"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"}
|