@acronis-platform/ui-react 5.1.0 → 5.2.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/chart-state/chart-state.js +15 -7
- package/dist/components/ui/chart-state/chart-state.js.map +1 -1
- package/dist/components/ui/checkbox/checkbox.js +1 -1
- package/dist/components/ui/checkbox/checkbox.js.map +1 -1
- package/dist/components/ui/combobox/combobox.js +1 -1
- package/dist/components/ui/combobox/combobox.js.map +1 -1
- package/dist/components/ui/dropdown-menu/dropdown-menu.js +2 -2
- package/dist/components/ui/dropdown-menu/dropdown-menu.js.map +1 -1
- package/dist/components/ui/input-num-picker/input-num-picker.js.map +1 -1
- package/dist/components/ui/input-select/input-select.js +1 -1
- package/dist/components/ui/input-select/input-select.js.map +1 -1
- package/dist/components/ui/number-field/number-field.js.map +1 -1
- package/dist/components/ui/sidebar-primary/sidebar-primary.js +10 -5
- package/dist/components/ui/sidebar-primary/sidebar-primary.js.map +1 -1
- package/dist/llms/chart-state.md +17 -4
- package/dist/llms/checkbox.md +63 -12
- package/dist/llms/sidebar-primary.md +18 -1
- package/dist/llms.txt +1 -1
- package/dist/src/components/ui/sidebar-primary/sidebar-primary.d.ts +23 -0
- package/dist/ui-react.css +1 -1
- package/package.json +2 -2
|
@@ -14,7 +14,7 @@ var s = {
|
|
|
14
14
|
let m = l ? n[l] : void 0, h = u ?? s[c];
|
|
15
15
|
return /* @__PURE__ */ a("div", {
|
|
16
16
|
ref: p,
|
|
17
|
-
className: e("flex size-full min-h-32 flex-col items-center
|
|
17
|
+
className: e("flex size-full min-h-32 flex-col items-center gap-2 text-center text-sm leading-6 text-foreground", c === "error" ? "overflow-y-auto overflow-x-hidden" : "justify-center", r),
|
|
18
18
|
...f,
|
|
19
19
|
role: c === "error" ? "alert" : "status",
|
|
20
20
|
"aria-live": c === "error" ? "assertive" : "polite",
|
|
@@ -24,12 +24,20 @@ var s = {
|
|
|
24
24
|
"aria-hidden": !0
|
|
25
25
|
}),
|
|
26
26
|
c === "empty" && m && /* @__PURE__ */ i(m, { className: "max-h-full w-full max-w-[220px] shrink text-[var(--ui-background-status-off)]" }),
|
|
27
|
-
c === "error"
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
27
|
+
c === "error" ? /* @__PURE__ */ a("div", {
|
|
28
|
+
className: "my-auto flex w-full flex-col items-center gap-2",
|
|
29
|
+
children: [
|
|
30
|
+
/* @__PURE__ */ i(o, {
|
|
31
|
+
size: 24,
|
|
32
|
+
className: "shrink-0 text-[var(--ui-glyph-on-status-warning)]"
|
|
33
|
+
}),
|
|
34
|
+
/* @__PURE__ */ i("p", {
|
|
35
|
+
className: "max-w-full break-words",
|
|
36
|
+
children: h
|
|
37
|
+
}),
|
|
38
|
+
d
|
|
39
|
+
]
|
|
40
|
+
}) : /* @__PURE__ */ i("p", { children: h })
|
|
33
41
|
]
|
|
34
42
|
});
|
|
35
43
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"chart-state.js","names":[],"sources":["../../../../src/components/ui/chart-state/chart-state.tsx"],"sourcesContent":["'use client';\n\nimport * as React from 'react';\nimport { CircleWarningIcon } from '@acronis-platform/icons-react/stroke-mono';\n\nimport { cn } from '@/lib/utils';\nimport { Spinner } from '../spinner';\nimport {\n CHART_STATE_ILLUSTRATIONS,\n type ChartStateVariant,\n} from './chart-state-illustrations';\n\n// A shared loading / empty / error placeholder for the chart types. A chart can\n// only render once recharts' `ResponsiveContainer` has data and real dimensions,\n// so every type needs the same \"there's nothing to plot yet\" surface — this is\n// that surface, dropped in place of the chart inside the same sized slot.\n//\n// Ported from the Figma InputSelect dropdown states (the reference the task\n// points at) and kept visually in step with the shipped `InputSelectStatus`\n// sibling: the empty / error states use the same 24px glyph + `text-sm` label\n// and the same `--ui-glyph-on-status-*` icon tokens. (Loading uses the shared\n// `Spinner` — brand blue, larger — not the sibling's inline gray ring.) No\n// `--ui-chart-*` tier exists yet, so it themes from existing semantic tokens\n// directly:\n// • label -> text-foreground (--ui-text-on-surface-primary)\n// • empty icon -> --ui-glyph-on-status-info\n// • error icon -> --ui-glyph-on-status-warning\n// • loading -> the shared Spinner (brand action blue)\n// The generic full-page `Empty` component is the larger, page-level sibling;\n// this one is compact and fills a chart slot.\n\nconst DEFAULT_MESSAGE: Record<ChartStateProps['state'], string> = {\n loading: 'Data is loading…',\n empty: 'No data found',\n error: 'Something went wrong',\n};\n\nexport interface ChartStateProps extends Omit<\n React.ComponentPropsWithoutRef<'div'>,\n 'children'\n> {\n /** Which placeholder to show. Drives the leading glyph and default label. */\n state: 'loading' | 'empty' | 'error';\n /**\n * Which chart the slot holds. `empty` then draws that type's silhouette\n * instead of the generic inbox glyph — the design defines one per chart type.\n * Ignored by `loading` and `error`, which share one treatment.\n */\n variant?: ChartStateVariant;\n /**\n * Text shown below the illustration or glyph. Defaults to `\"Data is\n * loading…\"` / `\"No data found\"` / `\"Something went wrong\"` based on\n * `state`. Pass a value to override for any state.\n */\n description?: React.ReactNode;\n /** Trailing action (e.g. a \"Try again\" button) — shown for `error` only. */\n action?: React.ReactNode;\n}\n\nconst ChartState = React.forwardRef<HTMLDivElement, ChartStateProps>(\n (\n { className, state, variant, description, action, ...props },\n ref\n ) => {\n const Illustration = variant\n ? CHART_STATE_ILLUSTRATIONS[variant]\n : undefined;\n const caption = description ?? DEFAULT_MESSAGE[state];\n\n return (\n <div\n ref={ref}\n className={cn(\n 'flex size-full min-h-32 flex-col items-center
|
|
1
|
+
{"version":3,"file":"chart-state.js","names":[],"sources":["../../../../src/components/ui/chart-state/chart-state.tsx"],"sourcesContent":["'use client';\n\nimport * as React from 'react';\nimport { CircleWarningIcon } from '@acronis-platform/icons-react/stroke-mono';\n\nimport { cn } from '@/lib/utils';\nimport { Spinner } from '../spinner';\nimport {\n CHART_STATE_ILLUSTRATIONS,\n type ChartStateVariant,\n} from './chart-state-illustrations';\n\n// A shared loading / empty / error placeholder for the chart types. A chart can\n// only render once recharts' `ResponsiveContainer` has data and real dimensions,\n// so every type needs the same \"there's nothing to plot yet\" surface — this is\n// that surface, dropped in place of the chart inside the same sized slot.\n//\n// Ported from the Figma InputSelect dropdown states (the reference the task\n// points at) and kept visually in step with the shipped `InputSelectStatus`\n// sibling: the empty / error states use the same 24px glyph + `text-sm` label\n// and the same `--ui-glyph-on-status-*` icon tokens. (Loading uses the shared\n// `Spinner` — brand blue, larger — not the sibling's inline gray ring.) No\n// `--ui-chart-*` tier exists yet, so it themes from existing semantic tokens\n// directly:\n// • label -> text-foreground (--ui-text-on-surface-primary)\n// • empty icon -> --ui-glyph-on-status-info\n// • error icon -> --ui-glyph-on-status-warning\n// • loading -> the shared Spinner (brand action blue)\n// The generic full-page `Empty` component is the larger, page-level sibling;\n// this one is compact and fills a chart slot.\n\nconst DEFAULT_MESSAGE: Record<ChartStateProps['state'], string> = {\n loading: 'Data is loading…',\n empty: 'No data found',\n error: 'Something went wrong',\n};\n\nexport interface ChartStateProps extends Omit<\n React.ComponentPropsWithoutRef<'div'>,\n 'children'\n> {\n /** Which placeholder to show. Drives the leading glyph and default label. */\n state: 'loading' | 'empty' | 'error';\n /**\n * Which chart the slot holds. `empty` then draws that type's silhouette\n * instead of the generic inbox glyph — the design defines one per chart type.\n * Ignored by `loading` and `error`, which share one treatment.\n */\n variant?: ChartStateVariant;\n /**\n * Text shown below the illustration or glyph. Defaults to `\"Data is\n * loading…\"` / `\"No data found\"` / `\"Something went wrong\"` based on\n * `state`. Pass a value to override for any state.\n */\n description?: React.ReactNode;\n /** Trailing action (e.g. a \"Try again\" button) — shown for `error` only. */\n action?: React.ReactNode;\n}\n\nconst ChartState = React.forwardRef<HTMLDivElement, ChartStateProps>(\n (\n { className, state, variant, description, action, ...props },\n ref\n ) => {\n const Illustration = variant\n ? CHART_STATE_ILLUSTRATIONS[variant]\n : undefined;\n const caption = description ?? DEFAULT_MESSAGE[state];\n\n return (\n <div\n ref={ref}\n className={cn(\n 'flex size-full min-h-32 flex-col items-center gap-2 text-center text-sm leading-6 text-foreground',\n // Error: scroll long diagnostic text instead of overflowing the card.\n // Loading/empty keep centered — their content is always compact.\n state === 'error'\n ? 'overflow-y-auto overflow-x-hidden'\n : 'justify-center',\n className\n )}\n {...props}\n // The status/alert live-region contract is intrinsic to the state, so it\n // wins over any consumer-passed a11y prop (spread above). No `aria-busy`\n // here: this element IS the live region, and some AT defer announcing a\n // busy region's content until busy clears — but this placeholder is\n // unmounted (swapped for the chart) rather than un-busied, so a busy flag\n // would risk swallowing the \"Data is loading…\" announcement. A consumer\n // that wants a busy signal sets `aria-busy` on the chart-slot container.\n role={state === 'error' ? 'alert' : 'status'}\n aria-live={state === 'error' ? 'assertive' : 'polite'}\n >\n {/* aria-hidden: the root is already the loading live region (+ the label),\n so the Spinner's own role=\"status\"/sr-only would double-announce. */}\n {state === 'loading' && <Spinner size=\"lg\" aria-hidden />}\n {state === 'empty' && Illustration && (\n // The tone is set once here, and every path inside is `currentColor`,\n // so brand and theme overrides follow. Figma binds the artwork to\n // `components/Avatar/color/blue`; this is the semantic token with the\n // identical light/dark pair, and \"status off\" is what an empty widget\n // is — referencing Avatar's tier from a chart would be a coupling with\n // no meaning behind it.\n // Scales with the slot rather than sitting at the mockup's 147×92:\n // the silhouette is the whole point of a per-type empty state, so it\n // takes the room the card gives it, capped so it stays a thumbnail\n // in a wide widget instead of a poster.\n <Illustration className=\"max-h-full w-full max-w-[220px] shrink text-[var(--ui-background-status-off)]\" />\n )}\n {/* Error content is wrapped so `my-auto` can center it when the card\n is tall (margins split the space) yet collapse to top-aligned when\n the text overflows (margins collapse to 0 → scrollable from the\n top). `justify-center` alone would push the icon above the visible\n area on overflow; `justify-start` alone would top-align even short\n messages. `shrink-0` on the icon prevents flex from compressing it\n when the description is long. */}\n {state === 'error' ? (\n <div className=\"my-auto flex w-full flex-col items-center gap-2\">\n <CircleWarningIcon\n size={24}\n className=\"shrink-0 text-[var(--ui-glyph-on-status-warning)]\"\n />\n <p className=\"max-w-full break-words\">{caption}</p>\n {action}\n </div>\n ) : (\n <p>{caption}</p>\n )}\n </div>\n );\n }\n);\nChartState.displayName = 'ChartState';\n\nexport { ChartState };\n"],"mappings":";;;;;;;;AA+BA,IAAM,IAA4D;CAChE,SAAS;CACT,OAAO;CACP,OAAO;AACT,GAwBM,IAAa,EAAM,YAErB,EAAE,cAAW,UAAO,YAAS,gBAAa,WAAQ,GAAG,KACrD,MACG;CACH,IAAM,IAAe,IACjB,EAA0B,KAC1B,KAAA,GACE,IAAU,KAAe,EAAgB;CAE/C,OACE,kBAAC,OAAD;EACO;EACL,WAAW,EACT,qGAGA,MAAU,UACN,sCACA,kBACJ,CACF;EACA,GAAI;EAQJ,MAAM,MAAU,UAAU,UAAU;EACpC,aAAW,MAAU,UAAU,cAAc;EApB/C,UAAA;GAwBG,MAAU,aAAa,kBAAC,GAAD;IAAS,MAAK;IAAK,eAAA;GAAa,CAAA;GACvD,MAAU,WAAW,KAWpB,kBAAC,GAAD,EAAc,WAAU,gFAAiF,CAAA;GAS1G,MAAU,UACT,kBAAC,OAAD;IAAK,WAAU;IAAf,UAAA;KACE,kBAAC,GAAD;MACE,MAAM;MACN,WAAU;KACX,CAAA;KACD,kBAAC,KAAD;MAAG,WAAU;MAA0B,UAAA;KAAW,CAAA;KACjD;IACE;GAEL,CAAA,IAAA,kBAAC,KAAD,EAAA,UAAI,EAAW,CAAA;EAEd;;AAET,CACF;AACA,EAAW,cAAc"}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { cn as e } from "../../../lib/utils.js";
|
|
2
2
|
import * as t from "react";
|
|
3
3
|
import { jsx as n, jsxs as r } from "react/jsx-runtime";
|
|
4
|
-
import {
|
|
4
|
+
import { CheckSmallIcon as i, MinusSmallIcon as a } from "@acronis-platform/icons-react/stroke-mono";
|
|
5
5
|
import { Checkbox as o } from "@base-ui/react/checkbox";
|
|
6
6
|
//#region src/components/ui/checkbox/checkbox.tsx
|
|
7
7
|
var s = [
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"checkbox.js","names":[],"sources":["../../../../src/components/ui/checkbox/checkbox.tsx"],"sourcesContent":["import * as React from 'react';\nimport { Checkbox as CheckboxPrimitive } from '@base-ui/react/checkbox';\nimport {\n
|
|
1
|
+
{"version":3,"file":"checkbox.js","names":[],"sources":["../../../../src/components/ui/checkbox/checkbox.tsx"],"sourcesContent":["import * as React from 'react';\nimport { Checkbox as CheckboxPrimitive } from '@base-ui/react/checkbox';\nimport {\n CheckSmallIcon,\n MinusSmallIcon,\n} from '@acronis-platform/icons-react/stroke-mono';\n\nimport { cn } from '@/lib/utils';\n\n// Wraps Base UI's Checkbox primitive, themed by the dedicated next-gen\n// `--ui-checkbox-*` token tier from @acronis-platform/tokens-pd. The box has three\n// logical states — `unchecked` (the base), `checked`, and `indeterminate` — each\n// with its own per-interaction (idle / hover / active / disabled) fill\n// (`*-box-color-*`), border (`*-box-border-color-*`), and glyph (`*-icon-color-*`)\n// tokens. `unchecked` is the base layer (lowest specificity); `data-[checked]` /\n// `data-[indeterminate]` override it (Base UI marks an indeterminate box with both\n// data-unchecked AND data-indeterminate, so the single-attribute overrides win on\n// specificity), and `data-[disabled]:data-[<state>]` overrides those in turn. The\n// glyph (check when checked, minus when indeterminate) inherits the Root's text\n// color via the Indicator's `text-current`. Box geometry (16px size, 2px radius)\n// comes from `--ui-checkbox-global-box-*`; the focus ring uses `--ui-focus-primary`.\n//\n// An optional `label` / `description` compose the full Figma field: the box, an\n// optional label, and an optional description stacked beside it. When either is\n// present the whole row is a `<label>` (so clicking the text toggles the box — a\n// Base UI checkbox renders a labelable <button>), the box gets a top margin of\n// `--ui-checkbox-global-box-margin-y` (4px = (line-height 24 − box 16) / 2, the\n// design's box alignment margin) to center it on the first text line, and the\n// box is wired to the text via aria-labelledby / aria-describedby. With neither,\n// the box renders on its own (name it with `aria-label`).\nconst boxClasses = [\n // geometry + focus ring\n // `align-middle` keeps the box vertically centered when it sits inline next to\n // text (e.g. in a table cell) rather than defaulting to the text baseline.\n 'inline-flex size-[var(--ui-checkbox-global-box-size)] shrink-0 cursor-pointer items-center justify-center rounded-[var(--ui-checkbox-global-box-border-radius)] border align-middle transition-colors focus-visible:outline-none focus-visible:ring-[3px] focus-visible:ring-[var(--ui-focus-primary)] [&_svg]:shrink-0',\n // unchecked (base): idle / hover / active\n 'bg-[var(--ui-checkbox-unchecked-box-color-idle)] border-[var(--ui-checkbox-unchecked-box-border-color-idle)]',\n 'not-data-[disabled]:hover:bg-[var(--ui-checkbox-unchecked-box-color-hover)] not-data-[disabled]:hover:border-[var(--ui-checkbox-unchecked-box-border-color-hover)]',\n 'not-data-[disabled]:active:bg-[var(--ui-checkbox-unchecked-box-color-active)] not-data-[disabled]:active:border-[var(--ui-checkbox-unchecked-box-border-color-active)]',\n // checked: idle / hover / active\n 'data-[checked]:bg-[var(--ui-checkbox-checked-box-color-idle)] data-[checked]:border-[var(--ui-checkbox-checked-box-border-color-idle)] data-[checked]:text-[var(--ui-checkbox-checked-icon-color-idle)]',\n 'data-[checked]:not-data-[disabled]:hover:bg-[var(--ui-checkbox-checked-box-color-hover)] data-[checked]:not-data-[disabled]:hover:border-[var(--ui-checkbox-checked-box-border-color-hover)] data-[checked]:not-data-[disabled]:hover:text-[var(--ui-checkbox-checked-icon-color-hover)]',\n 'data-[checked]:not-data-[disabled]:active:bg-[var(--ui-checkbox-checked-box-color-active)] data-[checked]:not-data-[disabled]:active:border-[var(--ui-checkbox-checked-box-border-color-active)] data-[checked]:not-data-[disabled]:active:text-[var(--ui-checkbox-checked-icon-color-active)]',\n // indeterminate: idle / hover / active\n 'data-[indeterminate]:bg-[var(--ui-checkbox-indeterminate-box-color-idle)] data-[indeterminate]:border-[var(--ui-checkbox-indeterminate-box-border-color-idle)] data-[indeterminate]:text-[var(--ui-checkbox-indeterminate-icon-color-idle)]',\n 'data-[indeterminate]:not-data-[disabled]:hover:bg-[var(--ui-checkbox-indeterminate-box-color-hover)] data-[indeterminate]:not-data-[disabled]:hover:border-[var(--ui-checkbox-indeterminate-box-border-color-hover)] data-[indeterminate]:not-data-[disabled]:hover:text-[var(--ui-checkbox-indeterminate-icon-color-hover)]',\n 'data-[indeterminate]:not-data-[disabled]:active:bg-[var(--ui-checkbox-indeterminate-box-color-active)] data-[indeterminate]:not-data-[disabled]:active:border-[var(--ui-checkbox-indeterminate-box-border-color-active)] data-[indeterminate]:not-data-[disabled]:active:text-[var(--ui-checkbox-indeterminate-icon-color-active)]',\n // disabled (unchecked base + per-state overrides)\n 'data-[disabled]:cursor-not-allowed data-[disabled]:bg-[var(--ui-checkbox-unchecked-box-color-disabled)] data-[disabled]:border-[var(--ui-checkbox-unchecked-box-border-color-disabled)]',\n 'data-[disabled]:data-[checked]:bg-[var(--ui-checkbox-checked-box-color-disabled)] data-[disabled]:data-[checked]:border-[var(--ui-checkbox-checked-box-border-color-disabled)] data-[disabled]:data-[checked]:text-[var(--ui-checkbox-checked-icon-color-disabled)]',\n 'data-[disabled]:data-[indeterminate]:bg-[var(--ui-checkbox-indeterminate-box-color-disabled)] data-[disabled]:data-[indeterminate]:border-[var(--ui-checkbox-indeterminate-box-border-color-disabled)] data-[disabled]:data-[indeterminate]:text-[var(--ui-checkbox-indeterminate-icon-color-disabled)]',\n].join(' ');\n\nexport interface CheckboxProps\n extends React.ComponentPropsWithoutRef<typeof CheckboxPrimitive.Root> {\n /** Optional label rendered beside the box; names the control. */\n label?: React.ReactNode;\n /** Optional secondary description rendered under the label. */\n description?: React.ReactNode;\n}\n\nconst Checkbox = React.forwardRef<\n React.ElementRef<typeof CheckboxPrimitive.Root>,\n CheckboxProps\n>(({ className, label, description, indeterminate, ...props }, ref) => {\n const reactId = React.useId();\n const labelId = label != null ? `${reactId}-label` : undefined;\n const descriptionId = description != null ? `${reactId}-description` : undefined;\n const hasContent = label != null || description != null;\n\n const box = (\n <CheckboxPrimitive.Root\n ref={ref}\n indeterminate={indeterminate}\n aria-labelledby={labelId}\n aria-describedby={descriptionId}\n className={cn(\n boxClasses,\n hasContent && 'mt-[var(--ui-checkbox-global-box-margin-y)]',\n className\n )}\n {...props}\n >\n <CheckboxPrimitive.Indicator className=\"flex items-center justify-center text-current\">\n {indeterminate ? (\n <MinusSmallIcon size={16} className=\"text-current!\" />\n ) : (\n <CheckSmallIcon size={16} className=\"text-current!\" />\n )}\n </CheckboxPrimitive.Indicator>\n </CheckboxPrimitive.Root>\n );\n\n if (!hasContent) return box;\n\n return (\n <label className=\"inline-flex max-w-[var(--ui-checkbox-global-container-width-max)] min-w-[var(--ui-checkbox-global-container-width-min)] cursor-pointer items-start gap-[var(--ui-checkbox-global-container-gap)]\">\n {box}\n <span className=\"flex max-w-[var(--ui-checkbox-global-container-content-width-max)] flex-col gap-[var(--ui-checkbox-global-container-content-gap)]\">\n {label != null && (\n <span\n id={labelId}\n className=\"text-sm leading-6 font-normal text-[var(--ui-checkbox-global-label-color)]\"\n >\n {label}\n </span>\n )}\n {description != null && (\n <span\n id={descriptionId}\n className=\"text-sm leading-6 font-normal text-[var(--ui-checkbox-global-description-color)]\"\n >\n {description}\n </span>\n )}\n </span>\n </label>\n );\n});\nCheckbox.displayName = 'Checkbox';\n\nexport { Checkbox };\n"],"mappings":";;;;;;AA8BA,IAAM,IAAa;CAIjB;CAEA;CACA;CACA;CAEA;CACA;CACA;CAEA;CACA;CACA;CAEA;CACA;CACA;AACF,CAAC,CAAC,KAAK,GAAG,GAUJ,IAAW,EAAM,YAGpB,EAAE,cAAW,UAAO,gBAAa,kBAAe,GAAG,KAAS,MAAQ;CACrE,IAAM,IAAU,EAAM,MAAM,GACtB,IAAU,KAAS,OAA4B,KAAA,IAArB,GAAG,EAAQ,SACrC,IAAgB,KAAe,OAAkC,KAAA,IAA3B,GAAG,EAAQ,eACjD,IAAa,KAAS,QAAQ,KAAe,MAE7C,IACJ,kBAAC,EAAkB,MAAnB;EACO;EACU;EACf,mBAAiB;EACjB,oBAAkB;EAClB,WAAW,EACT,GACA,KAAc,+CACd,CACF;EACA,GAAI;EAEJ,UAAA,kBAAC,EAAkB,WAAnB;GAA6B,WAAU;GACpC,UACC,EADD,IACE,IAEA,GAFD;IAAgB,MAAM;IAAI,WAAU;GAAiB,CAEA;EAE5B,CAAA;CACP,CAAA;CAK1B,OAFK,IAGH,kBAAC,SAAD;EAAO,WAAU;EAAjB,UAAA,CACG,GACD,kBAAC,QAAD;GAAM,WAAU;GAAhB,UAAA,CACG,KAAS,QACR,kBAAC,QAAD;IACE,IAAI;IACJ,WAAU;IAET,UAAA;GACG,CAAA,GAEP,KAAe,QACd,kBAAC,QAAD;IACE,IAAI;IACJ,WAAU;IAET,UAAA;GACG,CAAA,CAEJ;EACD,CAAA,CAAA;MAvBe;AAyB1B,CAAC;AACD,EAAS,cAAc"}
|
|
@@ -3,7 +3,7 @@ import { cn as e } from "../../../lib/utils.js";
|
|
|
3
3
|
import { usePortalContainer as t } from "../../../lib/portal-container.js";
|
|
4
4
|
import * as n from "react";
|
|
5
5
|
import { jsx as r, jsxs as i } from "react/jsx-runtime";
|
|
6
|
-
import {
|
|
6
|
+
import { CheckSmallIcon as a, ChevronDownIcon as o, TimesIcon as s } from "@acronis-platform/icons-react/stroke-mono";
|
|
7
7
|
import { Combobox as c } from "@base-ui/react/combobox";
|
|
8
8
|
//#region src/components/ui/combobox/combobox.tsx
|
|
9
9
|
function l(e) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"combobox.js","names":[],"sources":["../../../../src/components/ui/combobox/combobox.tsx"],"sourcesContent":["'use client';\n\nimport * as React from 'react';\nimport { Combobox as ComboboxPrimitive } from '@base-ui/react/combobox';\nimport {\n CheckIcon,\n ChevronDownIcon,\n TimesIcon,\n} from '@acronis-platform/icons-react/stroke-mono';\n\nimport { cn } from '@/lib/utils';\nimport { usePortalContainer } from '@/lib/portal-container';\n\n// A searchable single/multi-select built on Base UI's Combobox primitive. The\n// legacy `combobox` was only a hardcoded Popover + cmdk demo; this is a real,\n// reusable component. There is no `--ui-combobox-*` tier, so it reuses the\n// `--ui-input-select-*` tokens (already imported) — the field box, dropdown\n// container, and items match InputSelect, the non-searchable sibling. The Root\n// auto-extracts `{ value, label }` items and filters them by the input value.\n\nfunction Combobox<Value, Multiple extends boolean | undefined = false>(\n props: ComboboxPrimitive.Root.Props<Value, Multiple>\n) {\n return <ComboboxPrimitive.Root {...props} />;\n}\nCombobox.displayName = 'Combobox';\n\nexport interface ComboboxInputProps\n extends Omit<\n React.ComponentPropsWithoutRef<typeof ComboboxPrimitive.Input>,\n 'className'\n > {\n className?: string;\n /** Wrapper (box) className. */\n containerClassName?: string;\n /** Show a clear (✕) button while the field has a value. */\n clearable?: boolean;\n}\n\n// The field box: a typeable input + a clear button (optional) + a chevron trigger.\nconst ComboboxInput = React.forwardRef<\n HTMLInputElement,\n ComboboxInputProps\n>(({ className, containerClassName, clearable, ...props }, ref) => (\n // InputGroup (not a plain div) is the popup's anchor, so the dropdown aligns to\n // the box's left edge rather than to the bare input inside the box padding.\n <ComboboxPrimitive.InputGroup\n className={cn(\n 'group flex h-[var(--ui-input-select-global-box-height)] w-full min-w-0 items-center gap-[var(--ui-input-select-global-box-gap)] rounded-[var(--ui-input-select-global-box-border-radius)] border bg-[var(--ui-input-select-global-box-color-idle)] border-[var(--ui-input-select-normal-box-border-color-idle)] px-[var(--ui-input-select-global-box-padding-x)] text-sm leading-6 transition-colors',\n 'not-has-disabled:hover:bg-[var(--ui-input-select-global-box-color-hover)] not-has-disabled:hover:border-[var(--ui-input-select-normal-box-border-color-hover)]',\n 'has-[input:focus-visible]:border-[var(--ui-input-select-normal-box-border-color-hover)] has-[input:focus-visible]:ring-[3px] has-[input:focus-visible]:ring-[var(--ui-focus-primary)]',\n 'has-disabled:cursor-not-allowed has-disabled:border-[var(--ui-input-select-normal-box-border-color-disabled)] has-disabled:bg-[var(--ui-input-select-global-box-color-disabled)]',\n 'has-[input[aria-invalid=true]]:border-[var(--ui-input-select-error-box-border-color-idle)] has-[input[aria-invalid=true]:focus-visible]:ring-[var(--ui-focus-error)]',\n containerClassName\n )}\n >\n <ComboboxPrimitive.Input\n ref={ref}\n className={cn(\n 'min-w-0 flex-1 bg-transparent text-[var(--ui-input-select-global-value-color-idle)] outline-none placeholder:text-[var(--ui-input-select-global-placeholder-color-idle)] disabled:cursor-not-allowed disabled:text-[var(--ui-input-select-global-value-color-disabled)]',\n className\n )}\n {...props}\n />\n {clearable && (\n <ComboboxPrimitive.Clear\n aria-label=\"Clear\"\n className=\"flex shrink-0 cursor-pointer items-center text-[var(--ui-input-select-normal-icon-expand-color-idle)] outline-none focus-visible:ring-[3px] focus-visible:ring-[var(--ui-focus-primary)] data-[disabled]:hidden\"\n >\n <TimesIcon size={16} />\n </ComboboxPrimitive.Clear>\n )}\n <ComboboxPrimitive.Trigger\n aria-label=\"Toggle\"\n className=\"flex shrink-0 cursor-pointer items-center text-[var(--ui-input-select-normal-icon-expand-color-idle)] outline-none group-has-disabled:text-[var(--ui-input-select-normal-icon-expand-color-disabled)]\"\n >\n <ChevronDownIcon\n size={16}\n className=\"transition-transform group-has-[input[aria-expanded=true]]:rotate-180\"\n />\n </ComboboxPrimitive.Trigger>\n </ComboboxPrimitive.InputGroup>\n));\nComboboxInput.displayName = 'ComboboxInput';\n\nexport interface ComboboxContentProps\n extends React.ComponentPropsWithoutRef<typeof ComboboxPrimitive.Popup> {\n sideOffset?: number;\n align?: ComboboxPrimitive.Positioner.Props['align'];\n side?: ComboboxPrimitive.Positioner.Props['side'];\n /** Container to portal into (e.g. a shadow root, so the popup inherits styles). */\n portalContainer?: ComboboxPrimitive.Portal.Props['container'];\n}\n\nconst ComboboxContent = React.forwardRef<\n React.ElementRef<typeof ComboboxPrimitive.Popup>,\n ComboboxContentProps\n>(\n (\n { className, children, sideOffset = 4, align = 'start', side = 'bottom', portalContainer, ...props },\n ref\n ) => {\n const ctxContainer = usePortalContainer();\n const resolvedContainer = portalContainer ?? ctxContainer;\n\n return (\n <ComboboxPrimitive.Portal container={resolvedContainer}>\n <ComboboxPrimitive.Positioner\n sideOffset={sideOffset}\n align={align}\n side={side}\n className=\"z-50 outline-none\"\n >\n <ComboboxPrimitive.Popup\n ref={ref}\n className={cn(\n 'max-h-[var(--available-height)] min-w-[var(--anchor-width)] overflow-y-auto rounded-[var(--ui-input-select-dropdown-container-border-radius)] border border-[var(--ui-input-select-dropdown-container-border-color)] bg-[var(--ui-input-select-dropdown-container-color)] py-[var(--ui-input-select-dropdown-container-padding-y)] text-sm shadow-md outline-none',\n className\n )}\n {...props}\n >\n {children}\n </ComboboxPrimitive.Popup>\n </ComboboxPrimitive.Positioner>\n </ComboboxPrimitive.Portal>\n );\n }\n);\nComboboxContent.displayName = 'ComboboxContent';\n\nconst ComboboxList = React.forwardRef<\n React.ElementRef<typeof ComboboxPrimitive.List>,\n React.ComponentPropsWithoutRef<typeof ComboboxPrimitive.List>\n>(({ className, ...props }, ref) => (\n <ComboboxPrimitive.List\n ref={ref}\n className={cn('flex flex-col', className)}\n {...props}\n />\n));\nComboboxList.displayName = 'ComboboxList';\n\nconst ComboboxItem = React.forwardRef<\n React.ElementRef<typeof ComboboxPrimitive.Item>,\n React.ComponentPropsWithoutRef<typeof ComboboxPrimitive.Item>\n>(({ className, children, ...props }, ref) => (\n <ComboboxPrimitive.Item\n ref={ref}\n className={cn(\n 'relative flex cursor-default items-center gap-[var(--ui-input-select-dropdown-item-global-container-gap)] px-[var(--ui-input-select-dropdown-item-global-container-padding-x)] py-[var(--ui-input-select-dropdown-item-global-container-padding-y)] leading-6 text-[var(--ui-input-select-dropdown-item-global-label-color)] outline-none select-none',\n 'bg-[var(--ui-input-select-dropdown-item-unselected-container-color-idle)] data-[highlighted]:bg-[var(--ui-input-select-dropdown-item-unselected-container-color-hover)]',\n 'data-[selected]:bg-[var(--ui-input-select-dropdown-item-selected-container-color-idle)] data-[selected]:data-[highlighted]:bg-[var(--ui-input-select-dropdown-item-selected-container-color-hover)]',\n 'data-[disabled]:pointer-events-none data-[disabled]:bg-[var(--ui-input-select-dropdown-item-unselected-container-color-disabled)]',\n className\n )}\n {...props}\n >\n <span className=\"min-w-0 flex-1 truncate\">{children}</span>\n <ComboboxPrimitive.ItemIndicator className=\"flex shrink-0 items-center text-[var(--ui-input-select-normal-icon-expand-color-hover)]\">\n <CheckIcon size={16} />\n </ComboboxPrimitive.ItemIndicator>\n </ComboboxPrimitive.Item>\n));\nComboboxItem.displayName = 'ComboboxItem';\n\nconst ComboboxEmpty = React.forwardRef<\n React.ElementRef<typeof ComboboxPrimitive.Empty>,\n React.ComponentPropsWithoutRef<typeof ComboboxPrimitive.Empty>\n>(({ className, ...props }, ref) => (\n <ComboboxPrimitive.Empty\n ref={ref}\n className={cn(\n 'px-[var(--ui-input-select-dropdown-item-global-container-padding-x)] py-[var(--ui-input-select-dropdown-item-global-container-padding-y)] text-center text-sm leading-6 text-[var(--ui-input-select-normal-description-color-idle)] empty:m-0 empty:p-0',\n className\n )}\n {...props}\n />\n));\nComboboxEmpty.displayName = 'ComboboxEmpty';\n\nconst ComboboxGroup = ComboboxPrimitive.Group;\n\nconst ComboboxGroupLabel = React.forwardRef<\n React.ElementRef<typeof ComboboxPrimitive.GroupLabel>,\n React.ComponentPropsWithoutRef<typeof ComboboxPrimitive.GroupLabel>\n>(({ className, ...props }, ref) => (\n <ComboboxPrimitive.GroupLabel\n ref={ref}\n className={cn(\n 'px-[var(--ui-input-select-dropdown-section-container-header-padding-x)] py-[var(--ui-input-select-dropdown-section-container-header-padding-y)] text-sm font-semibold leading-6 text-[var(--ui-input-select-dropdown-section-label-group-color)]',\n className\n )}\n {...props}\n />\n));\nComboboxGroupLabel.displayName = 'ComboboxGroupLabel';\n\nexport {\n Combobox,\n ComboboxInput,\n ComboboxContent,\n ComboboxList,\n ComboboxItem,\n ComboboxEmpty,\n ComboboxGroup,\n ComboboxGroupLabel,\n};\n"],"mappings":";;;;;;;;AAoBA,SAAS,EACP,GACA;CACA,OAAO,kBAAC,EAAkB,MAAnB,EAAwB,GAAI,EAAQ,CAAA;AAC7C;AACA,EAAS,cAAc;AAevB,IAAM,IAAgB,EAAM,YAGzB,EAAE,cAAW,uBAAoB,cAAW,GAAG,KAAS,MAGzD,kBAAC,EAAkB,YAAnB;CACE,WAAW,EACT,wYACA,kKACA,yLACA,oLACA,wKACA,CACF;CARF,UAAA;EAUE,kBAAC,EAAkB,OAAnB;GACO;GACL,WAAW,EACT,2QACA,CACF;GACA,GAAI;EACL,CAAA;EACA,KACC,kBAAC,EAAkB,OAAnB;GACE,cAAW;GACX,WAAU;GAEV,UAAA,kBAAC,GAAD,EAAW,MAAM,GAAK,CAAA;EACC,CAAA;EAE3B,kBAAC,EAAkB,SAAnB;GACE,cAAW;GACX,WAAU;GAEV,UAAA,kBAAC,GAAD;IACE,MAAM;IACN,WAAU;GACX,CAAA;EACwB,CAAA;CACC;AAC/B,CAAA,CAAA;AACD,EAAc,cAAc;AAW5B,IAAM,IAAkB,EAAM,YAK1B,EAAE,cAAW,aAAU,gBAAa,GAAG,WAAQ,SAAS,UAAO,UAAU,oBAAiB,GAAG,KAC7F,MACG;CACH,IAAM,IAAe,EAAmB,GAClC,IAAoB,KAAmB;CAE7C,OACA,kBAAC,EAAkB,QAAnB;EAA0B,WAAW;EACnC,UAAA,kBAAC,EAAkB,YAAnB;GACc;GACL;GACD;GACN,WAAU;GAEV,UAAA,kBAAC,EAAkB,OAAnB;IACO;IACL,WAAW,EACT,qWACA,CACF;IACA,GAAI;IAEH;GACsB,CAAA;EACG,CAAA;CACN,CAAA;AAE5B,CACF;AACA,EAAgB,cAAc;AAE9B,IAAM,IAAe,EAAM,YAGxB,EAAE,cAAW,GAAG,KAAS,MAC1B,kBAAC,EAAkB,MAAnB;CACO;CACL,WAAW,EAAG,iBAAiB,CAAS;CACxC,GAAI;AACL,CAAA,CACF;AACD,EAAa,cAAc;AAE3B,IAAM,IAAe,EAAM,YAGxB,EAAE,cAAW,aAAU,GAAG,KAAS,MACpC,kBAAC,EAAkB,MAAnB;CACO;CACL,WAAW,EACT,yVACA,2KACA,uMACA,qIACA,CACF;CACA,GAAI;CATN,UAAA,CAWE,kBAAC,QAAD;EAAM,WAAU;EAA2B;CAAe,CAAA,GAC1D,kBAAC,EAAkB,eAAnB;EAAiC,WAAU;EACzC,UAAA,kBAAC,GAAD,EAAW,MAAM,GAAK,CAAA;CACS,CAAA,CACX;AACzB,CAAA,CAAA;AACD,EAAa,cAAc;AAE3B,IAAM,IAAgB,EAAM,YAGzB,EAAE,cAAW,GAAG,KAAS,MAC1B,kBAAC,EAAkB,OAAnB;CACO;CACL,WAAW,EACT,2PACA,CACF;CACA,GAAI;AACL,CAAA,CACF;AACD,EAAc,cAAc;AAE5B,IAAM,IAAgB,EAAkB,OAElC,IAAqB,EAAM,YAG9B,EAAE,cAAW,GAAG,KAAS,MAC1B,kBAAC,EAAkB,YAAnB;CACO;CACL,WAAW,EACT,oPACA,CACF;CACA,GAAI;AACL,CAAA,CACF;AACD,EAAmB,cAAc"}
|
|
1
|
+
{"version":3,"file":"combobox.js","names":[],"sources":["../../../../src/components/ui/combobox/combobox.tsx"],"sourcesContent":["'use client';\n\nimport * as React from 'react';\nimport { Combobox as ComboboxPrimitive } from '@base-ui/react/combobox';\nimport {\n CheckSmallIcon,\n ChevronDownIcon,\n TimesIcon,\n} from '@acronis-platform/icons-react/stroke-mono';\n\nimport { cn } from '@/lib/utils';\nimport { usePortalContainer } from '@/lib/portal-container';\n\n// A searchable single/multi-select built on Base UI's Combobox primitive. The\n// legacy `combobox` was only a hardcoded Popover + cmdk demo; this is a real,\n// reusable component. There is no `--ui-combobox-*` tier, so it reuses the\n// `--ui-input-select-*` tokens (already imported) — the field box, dropdown\n// container, and items match InputSelect, the non-searchable sibling. The Root\n// auto-extracts `{ value, label }` items and filters them by the input value.\n\nfunction Combobox<Value, Multiple extends boolean | undefined = false>(\n props: ComboboxPrimitive.Root.Props<Value, Multiple>\n) {\n return <ComboboxPrimitive.Root {...props} />;\n}\nCombobox.displayName = 'Combobox';\n\nexport interface ComboboxInputProps\n extends Omit<\n React.ComponentPropsWithoutRef<typeof ComboboxPrimitive.Input>,\n 'className'\n > {\n className?: string;\n /** Wrapper (box) className. */\n containerClassName?: string;\n /** Show a clear (✕) button while the field has a value. */\n clearable?: boolean;\n}\n\n// The field box: a typeable input + a clear button (optional) + a chevron trigger.\nconst ComboboxInput = React.forwardRef<\n HTMLInputElement,\n ComboboxInputProps\n>(({ className, containerClassName, clearable, ...props }, ref) => (\n // InputGroup (not a plain div) is the popup's anchor, so the dropdown aligns to\n // the box's left edge rather than to the bare input inside the box padding.\n <ComboboxPrimitive.InputGroup\n className={cn(\n 'group flex h-[var(--ui-input-select-global-box-height)] w-full min-w-0 items-center gap-[var(--ui-input-select-global-box-gap)] rounded-[var(--ui-input-select-global-box-border-radius)] border bg-[var(--ui-input-select-global-box-color-idle)] border-[var(--ui-input-select-normal-box-border-color-idle)] px-[var(--ui-input-select-global-box-padding-x)] text-sm leading-6 transition-colors',\n 'not-has-disabled:hover:bg-[var(--ui-input-select-global-box-color-hover)] not-has-disabled:hover:border-[var(--ui-input-select-normal-box-border-color-hover)]',\n 'has-[input:focus-visible]:border-[var(--ui-input-select-normal-box-border-color-hover)] has-[input:focus-visible]:ring-[3px] has-[input:focus-visible]:ring-[var(--ui-focus-primary)]',\n 'has-disabled:cursor-not-allowed has-disabled:border-[var(--ui-input-select-normal-box-border-color-disabled)] has-disabled:bg-[var(--ui-input-select-global-box-color-disabled)]',\n 'has-[input[aria-invalid=true]]:border-[var(--ui-input-select-error-box-border-color-idle)] has-[input[aria-invalid=true]:focus-visible]:ring-[var(--ui-focus-error)]',\n containerClassName\n )}\n >\n <ComboboxPrimitive.Input\n ref={ref}\n className={cn(\n 'min-w-0 flex-1 bg-transparent text-[var(--ui-input-select-global-value-color-idle)] outline-none placeholder:text-[var(--ui-input-select-global-placeholder-color-idle)] disabled:cursor-not-allowed disabled:text-[var(--ui-input-select-global-value-color-disabled)]',\n className\n )}\n {...props}\n />\n {clearable && (\n <ComboboxPrimitive.Clear\n aria-label=\"Clear\"\n className=\"flex shrink-0 cursor-pointer items-center text-[var(--ui-input-select-normal-icon-expand-color-idle)] outline-none focus-visible:ring-[3px] focus-visible:ring-[var(--ui-focus-primary)] data-[disabled]:hidden\"\n >\n <TimesIcon size={16} />\n </ComboboxPrimitive.Clear>\n )}\n <ComboboxPrimitive.Trigger\n aria-label=\"Toggle\"\n className=\"flex shrink-0 cursor-pointer items-center text-[var(--ui-input-select-normal-icon-expand-color-idle)] outline-none group-has-disabled:text-[var(--ui-input-select-normal-icon-expand-color-disabled)]\"\n >\n <ChevronDownIcon\n size={16}\n className=\"transition-transform group-has-[input[aria-expanded=true]]:rotate-180\"\n />\n </ComboboxPrimitive.Trigger>\n </ComboboxPrimitive.InputGroup>\n));\nComboboxInput.displayName = 'ComboboxInput';\n\nexport interface ComboboxContentProps\n extends React.ComponentPropsWithoutRef<typeof ComboboxPrimitive.Popup> {\n sideOffset?: number;\n align?: ComboboxPrimitive.Positioner.Props['align'];\n side?: ComboboxPrimitive.Positioner.Props['side'];\n /** Container to portal into (e.g. a shadow root, so the popup inherits styles). */\n portalContainer?: ComboboxPrimitive.Portal.Props['container'];\n}\n\nconst ComboboxContent = React.forwardRef<\n React.ElementRef<typeof ComboboxPrimitive.Popup>,\n ComboboxContentProps\n>(\n (\n { className, children, sideOffset = 4, align = 'start', side = 'bottom', portalContainer, ...props },\n ref\n ) => {\n const ctxContainer = usePortalContainer();\n const resolvedContainer = portalContainer ?? ctxContainer;\n\n return (\n <ComboboxPrimitive.Portal container={resolvedContainer}>\n <ComboboxPrimitive.Positioner\n sideOffset={sideOffset}\n align={align}\n side={side}\n className=\"z-50 outline-none\"\n >\n <ComboboxPrimitive.Popup\n ref={ref}\n className={cn(\n 'max-h-[var(--available-height)] min-w-[var(--anchor-width)] overflow-y-auto rounded-[var(--ui-input-select-dropdown-container-border-radius)] border border-[var(--ui-input-select-dropdown-container-border-color)] bg-[var(--ui-input-select-dropdown-container-color)] py-[var(--ui-input-select-dropdown-container-padding-y)] text-sm shadow-md outline-none',\n className\n )}\n {...props}\n >\n {children}\n </ComboboxPrimitive.Popup>\n </ComboboxPrimitive.Positioner>\n </ComboboxPrimitive.Portal>\n );\n }\n);\nComboboxContent.displayName = 'ComboboxContent';\n\nconst ComboboxList = React.forwardRef<\n React.ElementRef<typeof ComboboxPrimitive.List>,\n React.ComponentPropsWithoutRef<typeof ComboboxPrimitive.List>\n>(({ className, ...props }, ref) => (\n <ComboboxPrimitive.List\n ref={ref}\n className={cn('flex flex-col', className)}\n {...props}\n />\n));\nComboboxList.displayName = 'ComboboxList';\n\nconst ComboboxItem = React.forwardRef<\n React.ElementRef<typeof ComboboxPrimitive.Item>,\n React.ComponentPropsWithoutRef<typeof ComboboxPrimitive.Item>\n>(({ className, children, ...props }, ref) => (\n <ComboboxPrimitive.Item\n ref={ref}\n className={cn(\n 'relative flex cursor-default items-center gap-[var(--ui-input-select-dropdown-item-global-container-gap)] px-[var(--ui-input-select-dropdown-item-global-container-padding-x)] py-[var(--ui-input-select-dropdown-item-global-container-padding-y)] leading-6 text-[var(--ui-input-select-dropdown-item-global-label-color)] outline-none select-none',\n 'bg-[var(--ui-input-select-dropdown-item-unselected-container-color-idle)] data-[highlighted]:bg-[var(--ui-input-select-dropdown-item-unselected-container-color-hover)]',\n 'data-[selected]:bg-[var(--ui-input-select-dropdown-item-selected-container-color-idle)] data-[selected]:data-[highlighted]:bg-[var(--ui-input-select-dropdown-item-selected-container-color-hover)]',\n 'data-[disabled]:pointer-events-none data-[disabled]:bg-[var(--ui-input-select-dropdown-item-unselected-container-color-disabled)]',\n className\n )}\n {...props}\n >\n <span className=\"min-w-0 flex-1 truncate\">{children}</span>\n <ComboboxPrimitive.ItemIndicator className=\"flex shrink-0 items-center text-[var(--ui-input-select-normal-icon-expand-color-hover)]\">\n <CheckSmallIcon size={16} />\n </ComboboxPrimitive.ItemIndicator>\n </ComboboxPrimitive.Item>\n));\nComboboxItem.displayName = 'ComboboxItem';\n\nconst ComboboxEmpty = React.forwardRef<\n React.ElementRef<typeof ComboboxPrimitive.Empty>,\n React.ComponentPropsWithoutRef<typeof ComboboxPrimitive.Empty>\n>(({ className, ...props }, ref) => (\n <ComboboxPrimitive.Empty\n ref={ref}\n className={cn(\n 'px-[var(--ui-input-select-dropdown-item-global-container-padding-x)] py-[var(--ui-input-select-dropdown-item-global-container-padding-y)] text-center text-sm leading-6 text-[var(--ui-input-select-normal-description-color-idle)] empty:m-0 empty:p-0',\n className\n )}\n {...props}\n />\n));\nComboboxEmpty.displayName = 'ComboboxEmpty';\n\nconst ComboboxGroup = ComboboxPrimitive.Group;\n\nconst ComboboxGroupLabel = React.forwardRef<\n React.ElementRef<typeof ComboboxPrimitive.GroupLabel>,\n React.ComponentPropsWithoutRef<typeof ComboboxPrimitive.GroupLabel>\n>(({ className, ...props }, ref) => (\n <ComboboxPrimitive.GroupLabel\n ref={ref}\n className={cn(\n 'px-[var(--ui-input-select-dropdown-section-container-header-padding-x)] py-[var(--ui-input-select-dropdown-section-container-header-padding-y)] text-sm font-semibold leading-6 text-[var(--ui-input-select-dropdown-section-label-group-color)]',\n className\n )}\n {...props}\n />\n));\nComboboxGroupLabel.displayName = 'ComboboxGroupLabel';\n\nexport {\n Combobox,\n ComboboxInput,\n ComboboxContent,\n ComboboxList,\n ComboboxItem,\n ComboboxEmpty,\n ComboboxGroup,\n ComboboxGroupLabel,\n};\n"],"mappings":";;;;;;;;AAoBA,SAAS,EACP,GACA;CACA,OAAO,kBAAC,EAAkB,MAAnB,EAAwB,GAAI,EAAQ,CAAA;AAC7C;AACA,EAAS,cAAc;AAevB,IAAM,IAAgB,EAAM,YAGzB,EAAE,cAAW,uBAAoB,cAAW,GAAG,KAAS,MAGzD,kBAAC,EAAkB,YAAnB;CACE,WAAW,EACT,wYACA,kKACA,yLACA,oLACA,wKACA,CACF;CARF,UAAA;EAUE,kBAAC,EAAkB,OAAnB;GACO;GACL,WAAW,EACT,2QACA,CACF;GACA,GAAI;EACL,CAAA;EACA,KACC,kBAAC,EAAkB,OAAnB;GACE,cAAW;GACX,WAAU;GAEV,UAAA,kBAAC,GAAD,EAAW,MAAM,GAAK,CAAA;EACC,CAAA;EAE3B,kBAAC,EAAkB,SAAnB;GACE,cAAW;GACX,WAAU;GAEV,UAAA,kBAAC,GAAD;IACE,MAAM;IACN,WAAU;GACX,CAAA;EACwB,CAAA;CACC;AAC/B,CAAA,CAAA;AACD,EAAc,cAAc;AAW5B,IAAM,IAAkB,EAAM,YAK1B,EAAE,cAAW,aAAU,gBAAa,GAAG,WAAQ,SAAS,UAAO,UAAU,oBAAiB,GAAG,KAC7F,MACG;CACH,IAAM,IAAe,EAAmB,GAClC,IAAoB,KAAmB;CAE7C,OACA,kBAAC,EAAkB,QAAnB;EAA0B,WAAW;EACnC,UAAA,kBAAC,EAAkB,YAAnB;GACc;GACL;GACD;GACN,WAAU;GAEV,UAAA,kBAAC,EAAkB,OAAnB;IACO;IACL,WAAW,EACT,qWACA,CACF;IACA,GAAI;IAEH;GACsB,CAAA;EACG,CAAA;CACN,CAAA;AAE5B,CACF;AACA,EAAgB,cAAc;AAE9B,IAAM,IAAe,EAAM,YAGxB,EAAE,cAAW,GAAG,KAAS,MAC1B,kBAAC,EAAkB,MAAnB;CACO;CACL,WAAW,EAAG,iBAAiB,CAAS;CACxC,GAAI;AACL,CAAA,CACF;AACD,EAAa,cAAc;AAE3B,IAAM,IAAe,EAAM,YAGxB,EAAE,cAAW,aAAU,GAAG,KAAS,MACpC,kBAAC,EAAkB,MAAnB;CACO;CACL,WAAW,EACT,yVACA,2KACA,uMACA,qIACA,CACF;CACA,GAAI;CATN,UAAA,CAWE,kBAAC,QAAD;EAAM,WAAU;EAA2B;CAAe,CAAA,GAC1D,kBAAC,EAAkB,eAAnB;EAAiC,WAAU;EACzC,UAAA,kBAAC,GAAD,EAAgB,MAAM,GAAK,CAAA;CACI,CAAA,CACX;AACzB,CAAA,CAAA;AACD,EAAa,cAAc;AAE3B,IAAM,IAAgB,EAAM,YAGzB,EAAE,cAAW,GAAG,KAAS,MAC1B,kBAAC,EAAkB,OAAnB;CACO;CACL,WAAW,EACT,2PACA,CACF;CACA,GAAI;AACL,CAAA,CACF;AACD,EAAc,cAAc;AAE5B,IAAM,IAAgB,EAAkB,OAElC,IAAqB,EAAM,YAG9B,EAAE,cAAW,GAAG,KAAS,MAC1B,kBAAC,EAAkB,YAAnB;CACO;CACL,WAAW,EACT,oPACA,CACF;CACA,GAAI;AACL,CAAA,CACF;AACD,EAAmB,cAAc"}
|
|
@@ -2,7 +2,7 @@ import { cn as e } from "../../../lib/utils.js";
|
|
|
2
2
|
import { usePortalContainer as t } from "../../../lib/portal-container.js";
|
|
3
3
|
import * as n from "react";
|
|
4
4
|
import { jsx as r, jsxs as i } from "react/jsx-runtime";
|
|
5
|
-
import {
|
|
5
|
+
import { CheckSmallIcon as a, ChevronRightIcon as o } from "@acronis-platform/icons-react/stroke-mono";
|
|
6
6
|
import { Menu as s } from "@base-ui/react/menu";
|
|
7
7
|
//#region src/components/ui/dropdown-menu/dropdown-menu.tsx
|
|
8
8
|
var c = s.Root, l = s.Trigger, u = n.forwardRef(({ className: t, ...n }, i) => /* @__PURE__ */ r(s.Group, {
|
|
@@ -68,7 +68,7 @@ var S = n.forwardRef(({ className: t, children: n, ...o }, c) => /* @__PURE__ */
|
|
|
68
68
|
className: h,
|
|
69
69
|
children: /* @__PURE__ */ r(s.CheckboxItemIndicator, {
|
|
70
70
|
className: "flex",
|
|
71
|
-
children: /* @__PURE__ */ r(a, {
|
|
71
|
+
children: /* @__PURE__ */ r(a, { size: 16 })
|
|
72
72
|
})
|
|
73
73
|
}), n]
|
|
74
74
|
}));
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dropdown-menu.js","names":[],"sources":["../../../../src/components/ui/dropdown-menu/dropdown-menu.tsx"],"sourcesContent":["import * as React from 'react';\nimport { Menu as MenuPrimitive } from '@base-ui/react/menu';\nimport { CheckIcon, ChevronRightIcon } from '@acronis-platform/icons-react/stroke-mono';\n\nimport { cn } from '@/lib/utils';\nimport { usePortalContainer } from '@/lib/portal-container';\n\n// A menu of actions anchored to a trigger, built on the Base UI Menu primitive\n// (positioning, focus management, typeahead, outside-press / Esc dismissal,\n// ARIA). Themed from the `--ui-button-menu-dropdown-*` token tier generated by\n// @acronis-platform/tokens-pd (ButtonMenu/default.css). Enter/exit animations\n// use `tw-animate-css` keyed to data-[open]/[closed]/[side].\n\nconst DropdownMenu = MenuPrimitive.Root;\nconst DropdownMenuTrigger = MenuPrimitive.Trigger;\nconst DropdownMenuGroup = React.forwardRef<\n React.ElementRef<typeof MenuPrimitive.Group>,\n React.ComponentPropsWithoutRef<typeof MenuPrimitive.Group>\n>(({ className, ...props }, ref) => (\n <MenuPrimitive.Group\n ref={ref}\n className={cn(\n 'flex flex-col items-start overflow-clip gap-[var(--ui-button-menu-dropdown-section-list-gap)] px-[var(--ui-button-menu-dropdown-section-container-padding-x)] py-[var(--ui-button-menu-dropdown-section-container-padding-y)] [&:not(:first-child)]:border-t [&:not(:first-child)]:border-[length:var(--ui-button-menu-dropdown-section-container-border-width)] [&:not(:first-child)]:border-[var(--ui-button-menu-dropdown-section-container-border-color)]',\n className\n )}\n {...props}\n />\n));\nDropdownMenuGroup.displayName = 'DropdownMenuGroup';\nconst DropdownMenuPortal = MenuPrimitive.Portal;\nconst DropdownMenuSub = MenuPrimitive.SubmenuRoot;\n\nconst popupClassName =\n 'z-50 min-w-[8rem] overflow-y-auto overflow-x-hidden flex flex-col gap-[var(--ui-button-menu-dropdown-container-gap)] bg-[var(--ui-button-menu-dropdown-container-color)] border-solid border-[length:var(--ui-button-menu-dropdown-container-border-width)] border-[var(--ui-button-menu-dropdown-container-border-color)] rounded-[var(--ui-button-menu-dropdown-container-border-radius)] px-[var(--ui-button-menu-dropdown-container-padding-x)] py-[var(--ui-button-menu-dropdown-container-padding-y)] shadow-md outline-none duration-200 data-[open]:animate-in data-[closed]:animate-out data-[open]:fade-in-0 data-[closed]:fade-out-0 data-[open]:zoom-in-95 data-[closed]:zoom-out-95 data-[side=bottom]:slide-in-from-top-2 data-[side=top]:slide-in-from-bottom-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2';\n\nconst itemClassName =\n 'relative flex w-full shrink-0 cursor-default select-none items-start gap-[var(--ui-button-menu-dropdown-item-container-gap)] min-h-[var(--ui-button-menu-dropdown-item-container-height)] px-[var(--ui-button-menu-dropdown-item-container-padding-x)] py-[var(--ui-button-menu-dropdown-item-container-padding-y)] text-sm font-semibold leading-6 outline-none transition-colors bg-[var(--ui-button-menu-dropdown-item-container-color-idle)] text-[var(--ui-button-menu-dropdown-item-label-color)] [&_svg]:text-[var(--ui-button-menu-dropdown-item-icon-color)] data-[highlighted]:bg-[var(--ui-button-menu-dropdown-item-container-color-hover)] data-[highlighted]:active:bg-[var(--ui-button-menu-dropdown-item-container-color-active)] [&:focus-visible:not(:hover)]:rounded-[3px] [&:focus-visible:not(:hover)]:ring-[3px] [&:focus-visible:not(:hover)]:ring-inset [&:focus-visible:not(:hover)]:ring-[var(--ui-focus-primary)] data-[disabled]:pointer-events-none data-[disabled]:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0';\n\n// A checkbox/radio indicator lives in the same in-flow leading slot a menu-item\n// icon would occupy, so its label lands on the item gap grid (padding-x + 16px\n// glyph + gap) instead of a hardcoded indent. `h-6` matches the item's\n// line-height so the glyph centers on the first line of a wrapping label.\nconst indicatorSlotClassName =\n 'flex h-6 w-4 shrink-0 items-center justify-center text-[var(--ui-button-menu-dropdown-item-icon-color)]';\n\n// Indent for plain items/labels that must line up with the labels of sibling\n// checkbox/radio items.\nconst indicatorInsetClassName =\n 'ps-[calc(var(--ui-button-menu-dropdown-item-container-padding-x)+1rem+var(--ui-button-menu-dropdown-item-container-gap))]';\n\nexport interface DropdownMenuContentProps\n extends React.ComponentPropsWithoutRef<typeof MenuPrimitive.Popup> {\n side?: MenuPrimitive.Positioner.Props['side'];\n align?: MenuPrimitive.Positioner.Props['align'];\n sideOffset?: number;\n /** Render inside a portal (default `true`). */\n portal?: boolean;\n /** Portal container — pass a shadow-root mount for isolated-style previews. */\n portalContainer?: MenuPrimitive.Portal.Props['container'];\n keepMounted?: MenuPrimitive.Portal.Props['keepMounted'];\n}\n\nconst DropdownMenuContent = React.forwardRef<\n React.ElementRef<typeof MenuPrimitive.Popup>,\n DropdownMenuContentProps\n>(\n (\n {\n className,\n side,\n align,\n sideOffset = 4,\n portal = true,\n portalContainer,\n keepMounted,\n ...props\n },\n ref\n ) => {\n const ctxContainer = usePortalContainer();\n const resolvedContainer = portalContainer ?? ctxContainer;\n\n const positioner = (\n <MenuPrimitive.Positioner\n side={side}\n align={align}\n sideOffset={sideOffset}\n className=\"z-50\"\n >\n <MenuPrimitive.Popup\n ref={ref}\n className={cn(popupClassName, className)}\n {...props}\n />\n </MenuPrimitive.Positioner>\n );\n return portal ? (\n <MenuPrimitive.Portal container={resolvedContainer} keepMounted={keepMounted}>\n {positioner}\n </MenuPrimitive.Portal>\n ) : (\n positioner\n );\n }\n);\nDropdownMenuContent.displayName = 'DropdownMenuContent';\n\nconst DropdownMenuSubContent = React.forwardRef<\n React.ElementRef<typeof MenuPrimitive.Popup>,\n React.ComponentPropsWithoutRef<typeof MenuPrimitive.Popup> & {\n sideOffset?: number;\n }\n>(({ className, sideOffset = 4, ...props }, ref) => (\n <MenuPrimitive.Positioner sideOffset={sideOffset} className=\"z-50\">\n <MenuPrimitive.Popup\n ref={ref}\n className={cn(popupClassName, className)}\n {...props}\n />\n </MenuPrimitive.Positioner>\n));\nDropdownMenuSubContent.displayName = 'DropdownMenuSubContent';\n\nconst DropdownMenuItem = React.forwardRef<\n React.ElementRef<typeof MenuPrimitive.Item>,\n React.ComponentPropsWithoutRef<typeof MenuPrimitive.Item> & { inset?: boolean }\n>(({ className, inset, ...props }, ref) => (\n <MenuPrimitive.Item\n ref={ref}\n className={cn(itemClassName, inset && indicatorInsetClassName, className)}\n {...props}\n />\n));\nDropdownMenuItem.displayName = 'DropdownMenuItem';\n\nconst DropdownMenuSubTrigger = React.forwardRef<\n React.ElementRef<typeof MenuPrimitive.SubmenuTrigger>,\n React.ComponentPropsWithoutRef<typeof MenuPrimitive.SubmenuTrigger> & {\n inset?: boolean;\n }\n>(({ className, inset, children, ...props }, ref) => (\n <MenuPrimitive.SubmenuTrigger\n ref={ref}\n className={cn(\n itemClassName,\n 'data-[popup-open]:bg-[var(--ui-button-menu-dropdown-item-container-color-active)]',\n inset && indicatorInsetClassName,\n className\n )}\n {...props}\n >\n {children}\n <ChevronRightIcon className=\"ms-auto self-center text-[var(--ui-button-menu-dropdown-extras-cascade-icon-color)] rtl:rotate-180\" />\n </MenuPrimitive.SubmenuTrigger>\n));\nDropdownMenuSubTrigger.displayName = 'DropdownMenuSubTrigger';\n\n\nfunction DropdownMenuShortcut({\n className,\n ...props\n}: React.HTMLAttributes<HTMLSpanElement>) {\n return (\n <span\n className={cn('ms-auto shrink-0 text-sm font-normal leading-6 text-[var(--ui-button-menu-dropdown-extras-shortcut-label-color)]', className)}\n {...props}\n />\n );\n}\nDropdownMenuShortcut.displayName = 'DropdownMenuShortcut';\n\nconst DropdownMenuCheckboxItem = React.forwardRef<\n React.ElementRef<typeof MenuPrimitive.CheckboxItem>,\n React.ComponentPropsWithoutRef<typeof MenuPrimitive.CheckboxItem>\n>(({ className, children, ...props }, ref) => (\n <MenuPrimitive.CheckboxItem\n ref={ref}\n className={cn(itemClassName, className)}\n {...props}\n >\n <span className={indicatorSlotClassName}>\n <MenuPrimitive.CheckboxItemIndicator className=\"flex\">\n <CheckIcon className=\"size-4\" />\n </MenuPrimitive.CheckboxItemIndicator>\n </span>\n {children}\n </MenuPrimitive.CheckboxItem>\n));\nDropdownMenuCheckboxItem.displayName = 'DropdownMenuCheckboxItem';\n\nconst DropdownMenuRadioGroup = MenuPrimitive.RadioGroup;\n\nconst DropdownMenuRadioItem = React.forwardRef<\n React.ElementRef<typeof MenuPrimitive.RadioItem>,\n React.ComponentPropsWithoutRef<typeof MenuPrimitive.RadioItem>\n>(({ className, children, ...props }, ref) => (\n <MenuPrimitive.RadioItem\n ref={ref}\n className={cn(itemClassName, className)}\n {...props}\n >\n <span className={indicatorSlotClassName}>\n {/* The dot is the indicator element itself — Base UI renders it as a\n `<span>`, and an inline wrapper would collapse a sized child to 0. */}\n <MenuPrimitive.RadioItemIndicator className=\"block size-2 rounded-full bg-current\" />\n </span>\n {children}\n </MenuPrimitive.RadioItem>\n));\nDropdownMenuRadioItem.displayName = 'DropdownMenuRadioItem';\n\nconst DropdownMenuLabel = React.forwardRef<\n HTMLDivElement,\n React.HTMLAttributes<HTMLDivElement> & { inset?: boolean }\n>(({ className, inset, ...props }, ref) => (\n <div\n ref={ref}\n className={cn(\n 'px-[var(--ui-button-menu-dropdown-item-container-padding-x)] py-[var(--ui-button-menu-dropdown-item-container-padding-y)] text-sm font-semibold leading-6 text-[var(--ui-button-menu-dropdown-item-label-color)]',\n inset && indicatorInsetClassName,\n className\n )}\n {...props}\n />\n));\nDropdownMenuLabel.displayName = 'DropdownMenuLabel';\n\nconst DropdownMenuSeparator = React.forwardRef<\n HTMLDivElement,\n React.HTMLAttributes<HTMLDivElement>\n>(({ className, ...props }, ref) => (\n <div\n ref={ref}\n role=\"separator\"\n className={cn(\n 'my-[var(--ui-button-menu-dropdown-section-list-gap)] h-[var(--ui-button-menu-dropdown-section-container-border-width)] bg-[var(--ui-button-menu-dropdown-section-container-border-color)]',\n className\n )}\n {...props}\n />\n));\nDropdownMenuSeparator.displayName = 'DropdownMenuSeparator';\n\nexport {\n DropdownMenu,\n DropdownMenuTrigger,\n DropdownMenuContent,\n DropdownMenuGroup,\n DropdownMenuItem,\n DropdownMenuCheckboxItem,\n DropdownMenuRadioGroup,\n DropdownMenuRadioItem,\n DropdownMenuLabel,\n DropdownMenuSeparator,\n DropdownMenuShortcut,\n DropdownMenuSub,\n DropdownMenuSubContent,\n DropdownMenuSubTrigger,\n DropdownMenuPortal,\n};\n"],"mappings":";;;;;;;AAaA,IAAM,IAAe,EAAc,MAC7B,IAAsB,EAAc,SACpC,IAAoB,EAAM,YAG7B,EAAE,cAAW,GAAG,KAAS,MAC1B,kBAAC,EAAc,OAAf;CACO;CACL,WAAW,EACT,icACA,CACF;CACA,GAAI;AACL,CAAA,CACF;AACD,EAAkB,cAAc;AAChC,IAAM,IAAqB,EAAc,QACnC,IAAkB,EAAc,aAEhC,IACJ,g0BAEI,IACJ,2gCAMI,IACJ,2GAII,IACJ,6HAcI,IAAsB,EAAM,YAK9B,EACE,cACA,SACA,UACA,gBAAa,GACb,YAAS,IACT,oBACA,gBACA,GAAG,KAEL,MACG;CACH,IAAM,IAAe,EAAmB,GAClC,IAAoB,KAAmB,GAEvC,IACJ,kBAAC,EAAc,YAAf;EACQ;EACC;EACK;EACZ,WAAU;EAEV,UAAA,kBAAC,EAAc,OAAf;GACO;GACL,WAAW,EAAG,GAAgB,CAAS;GACvC,GAAI;EACL,CAAA;CACuB,CAAA;CAE5B,OAAO,IACL,kBAAC,EAAc,QAAf;EAAsB,WAAW;EAAgC;EAC9D,UAAA;CACmB,CAAA,IAEtB;AAEJ,CACF;AACA,EAAoB,cAAc;AAElC,IAAM,IAAyB,EAAM,YAKlC,EAAE,cAAW,gBAAa,GAAG,GAAG,KAAS,MAC1C,kBAAC,EAAc,YAAf;CAAsC;CAAY,WAAU;CAC1D,UAAA,kBAAC,EAAc,OAAf;EACO;EACL,WAAW,EAAG,GAAgB,CAAS;EACvC,GAAI;CACL,CAAA;AACuB,CAAA,CAC3B;AACD,EAAuB,cAAc;AAErC,IAAM,IAAmB,EAAM,YAG5B,EAAE,cAAW,UAAO,GAAG,KAAS,MACjC,kBAAC,EAAc,MAAf;CACO;CACL,WAAW,EAAG,GAAe,KAAS,GAAyB,CAAS;CACxE,GAAI;AACL,CAAA,CACF;AACD,EAAiB,cAAc;AAE/B,IAAM,IAAyB,EAAM,YAKlC,EAAE,cAAW,UAAO,aAAU,GAAG,KAAS,MAC3C,kBAAC,EAAc,gBAAf;CACO;CACL,WAAW,EACT,GACA,qFACA,KAAS,GACT,CACF;CACA,GAAI;CARN,UAAA,CAUG,GACD,kBAAC,GAAD,EAAkB,WAAU,qGAAsG,CAAA,CACtG;AAC/B,CAAA,CAAA;AACD,EAAuB,cAAc;AAGrC,SAAS,EAAqB,EAC5B,cACA,GAAG,KACqC;CACxC,OACE,kBAAC,QAAD;EACE,WAAW,EAAG,oHAAoH,CAAS;EAC3I,GAAI;CACL,CAAA;AAEL;AACA,EAAqB,cAAc;AAEnC,IAAM,IAA2B,EAAM,YAGpC,EAAE,cAAW,aAAU,GAAG,KAAS,MACpC,kBAAC,EAAc,cAAf;CACO;CACL,WAAW,EAAG,GAAe,CAAS;CACtC,GAAI;CAHN,UAAA,CAKE,kBAAC,QAAD;EAAM,WAAW;EACf,UAAA,kBAAC,EAAc,uBAAf;GAAqC,WAAU;GAC7C,UAAA,kBAAC,GAAD,EAAW,WAAU,SAAU,CAAA;EACI,CAAA;CACjC,CAAA,GACL,CACyB;AAC7B,CAAA,CAAA;AACD,EAAyB,cAAc;AAEvC,IAAM,IAAyB,EAAc,YAEvC,IAAwB,EAAM,YAGjC,EAAE,cAAW,aAAU,GAAG,KAAS,MACpC,kBAAC,EAAc,WAAf;CACO;CACL,WAAW,EAAG,GAAe,CAAS;CACtC,GAAI;CAHN,UAAA,CAKE,kBAAC,QAAD;EAAM,WAAW;EAGf,UAAA,kBAAC,EAAc,oBAAf,EAAkC,WAAU,uCAAwC,CAAA;CAChF,CAAA,GACL,CACsB;AAC1B,CAAA,CAAA;AACD,EAAsB,cAAc;AAEpC,IAAM,IAAoB,EAAM,YAG7B,EAAE,cAAW,UAAO,GAAG,KAAS,MACjC,kBAAC,OAAD;CACO;CACL,WAAW,EACT,oNACA,KAAS,GACT,CACF;CACA,GAAI;AACL,CAAA,CACF;AACD,EAAkB,cAAc;AAEhC,IAAM,IAAwB,EAAM,YAGjC,EAAE,cAAW,GAAG,KAAS,MAC1B,kBAAC,OAAD;CACO;CACL,MAAK;CACL,WAAW,EACT,6LACA,CACF;CACA,GAAI;AACL,CAAA,CACF;AACD,EAAsB,cAAc"}
|
|
1
|
+
{"version":3,"file":"dropdown-menu.js","names":[],"sources":["../../../../src/components/ui/dropdown-menu/dropdown-menu.tsx"],"sourcesContent":["import * as React from 'react';\nimport { Menu as MenuPrimitive } from '@base-ui/react/menu';\nimport { CheckSmallIcon, ChevronRightIcon } from '@acronis-platform/icons-react/stroke-mono';\n\nimport { cn } from '@/lib/utils';\nimport { usePortalContainer } from '@/lib/portal-container';\n\n// A menu of actions anchored to a trigger, built on the Base UI Menu primitive\n// (positioning, focus management, typeahead, outside-press / Esc dismissal,\n// ARIA). Themed from the `--ui-button-menu-dropdown-*` token tier generated by\n// @acronis-platform/tokens-pd (ButtonMenu/default.css). Enter/exit animations\n// use `tw-animate-css` keyed to data-[open]/[closed]/[side].\n\nconst DropdownMenu = MenuPrimitive.Root;\nconst DropdownMenuTrigger = MenuPrimitive.Trigger;\nconst DropdownMenuGroup = React.forwardRef<\n React.ElementRef<typeof MenuPrimitive.Group>,\n React.ComponentPropsWithoutRef<typeof MenuPrimitive.Group>\n>(({ className, ...props }, ref) => (\n <MenuPrimitive.Group\n ref={ref}\n className={cn(\n 'flex flex-col items-start overflow-clip gap-[var(--ui-button-menu-dropdown-section-list-gap)] px-[var(--ui-button-menu-dropdown-section-container-padding-x)] py-[var(--ui-button-menu-dropdown-section-container-padding-y)] [&:not(:first-child)]:border-t [&:not(:first-child)]:border-[length:var(--ui-button-menu-dropdown-section-container-border-width)] [&:not(:first-child)]:border-[var(--ui-button-menu-dropdown-section-container-border-color)]',\n className\n )}\n {...props}\n />\n));\nDropdownMenuGroup.displayName = 'DropdownMenuGroup';\nconst DropdownMenuPortal = MenuPrimitive.Portal;\nconst DropdownMenuSub = MenuPrimitive.SubmenuRoot;\n\nconst popupClassName =\n 'z-50 min-w-[8rem] overflow-y-auto overflow-x-hidden flex flex-col gap-[var(--ui-button-menu-dropdown-container-gap)] bg-[var(--ui-button-menu-dropdown-container-color)] border-solid border-[length:var(--ui-button-menu-dropdown-container-border-width)] border-[var(--ui-button-menu-dropdown-container-border-color)] rounded-[var(--ui-button-menu-dropdown-container-border-radius)] px-[var(--ui-button-menu-dropdown-container-padding-x)] py-[var(--ui-button-menu-dropdown-container-padding-y)] shadow-md outline-none duration-200 data-[open]:animate-in data-[closed]:animate-out data-[open]:fade-in-0 data-[closed]:fade-out-0 data-[open]:zoom-in-95 data-[closed]:zoom-out-95 data-[side=bottom]:slide-in-from-top-2 data-[side=top]:slide-in-from-bottom-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2';\n\nconst itemClassName =\n 'relative flex w-full shrink-0 cursor-default select-none items-start gap-[var(--ui-button-menu-dropdown-item-container-gap)] min-h-[var(--ui-button-menu-dropdown-item-container-height)] px-[var(--ui-button-menu-dropdown-item-container-padding-x)] py-[var(--ui-button-menu-dropdown-item-container-padding-y)] text-sm font-semibold leading-6 outline-none transition-colors bg-[var(--ui-button-menu-dropdown-item-container-color-idle)] text-[var(--ui-button-menu-dropdown-item-label-color)] [&_svg]:text-[var(--ui-button-menu-dropdown-item-icon-color)] data-[highlighted]:bg-[var(--ui-button-menu-dropdown-item-container-color-hover)] data-[highlighted]:active:bg-[var(--ui-button-menu-dropdown-item-container-color-active)] [&:focus-visible:not(:hover)]:rounded-[3px] [&:focus-visible:not(:hover)]:ring-[3px] [&:focus-visible:not(:hover)]:ring-inset [&:focus-visible:not(:hover)]:ring-[var(--ui-focus-primary)] data-[disabled]:pointer-events-none data-[disabled]:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0';\n\n// A checkbox/radio indicator lives in the same in-flow leading slot a menu-item\n// icon would occupy, so its label lands on the item gap grid (padding-x + 16px\n// glyph + gap) instead of a hardcoded indent. `h-6` matches the item's\n// line-height so the glyph centers on the first line of a wrapping label.\nconst indicatorSlotClassName =\n 'flex h-6 w-4 shrink-0 items-center justify-center text-[var(--ui-button-menu-dropdown-item-icon-color)]';\n\n// Indent for plain items/labels that must line up with the labels of sibling\n// checkbox/radio items.\nconst indicatorInsetClassName =\n 'ps-[calc(var(--ui-button-menu-dropdown-item-container-padding-x)+1rem+var(--ui-button-menu-dropdown-item-container-gap))]';\n\nexport interface DropdownMenuContentProps\n extends React.ComponentPropsWithoutRef<typeof MenuPrimitive.Popup> {\n side?: MenuPrimitive.Positioner.Props['side'];\n align?: MenuPrimitive.Positioner.Props['align'];\n sideOffset?: number;\n /** Render inside a portal (default `true`). */\n portal?: boolean;\n /** Portal container — pass a shadow-root mount for isolated-style previews. */\n portalContainer?: MenuPrimitive.Portal.Props['container'];\n keepMounted?: MenuPrimitive.Portal.Props['keepMounted'];\n}\n\nconst DropdownMenuContent = React.forwardRef<\n React.ElementRef<typeof MenuPrimitive.Popup>,\n DropdownMenuContentProps\n>(\n (\n {\n className,\n side,\n align,\n sideOffset = 4,\n portal = true,\n portalContainer,\n keepMounted,\n ...props\n },\n ref\n ) => {\n const ctxContainer = usePortalContainer();\n const resolvedContainer = portalContainer ?? ctxContainer;\n\n const positioner = (\n <MenuPrimitive.Positioner\n side={side}\n align={align}\n sideOffset={sideOffset}\n className=\"z-50\"\n >\n <MenuPrimitive.Popup\n ref={ref}\n className={cn(popupClassName, className)}\n {...props}\n />\n </MenuPrimitive.Positioner>\n );\n return portal ? (\n <MenuPrimitive.Portal container={resolvedContainer} keepMounted={keepMounted}>\n {positioner}\n </MenuPrimitive.Portal>\n ) : (\n positioner\n );\n }\n);\nDropdownMenuContent.displayName = 'DropdownMenuContent';\n\nconst DropdownMenuSubContent = React.forwardRef<\n React.ElementRef<typeof MenuPrimitive.Popup>,\n React.ComponentPropsWithoutRef<typeof MenuPrimitive.Popup> & {\n sideOffset?: number;\n }\n>(({ className, sideOffset = 4, ...props }, ref) => (\n <MenuPrimitive.Positioner sideOffset={sideOffset} className=\"z-50\">\n <MenuPrimitive.Popup\n ref={ref}\n className={cn(popupClassName, className)}\n {...props}\n />\n </MenuPrimitive.Positioner>\n));\nDropdownMenuSubContent.displayName = 'DropdownMenuSubContent';\n\nconst DropdownMenuItem = React.forwardRef<\n React.ElementRef<typeof MenuPrimitive.Item>,\n React.ComponentPropsWithoutRef<typeof MenuPrimitive.Item> & { inset?: boolean }\n>(({ className, inset, ...props }, ref) => (\n <MenuPrimitive.Item\n ref={ref}\n className={cn(itemClassName, inset && indicatorInsetClassName, className)}\n {...props}\n />\n));\nDropdownMenuItem.displayName = 'DropdownMenuItem';\n\nconst DropdownMenuSubTrigger = React.forwardRef<\n React.ElementRef<typeof MenuPrimitive.SubmenuTrigger>,\n React.ComponentPropsWithoutRef<typeof MenuPrimitive.SubmenuTrigger> & {\n inset?: boolean;\n }\n>(({ className, inset, children, ...props }, ref) => (\n <MenuPrimitive.SubmenuTrigger\n ref={ref}\n className={cn(\n itemClassName,\n 'data-[popup-open]:bg-[var(--ui-button-menu-dropdown-item-container-color-active)]',\n inset && indicatorInsetClassName,\n className\n )}\n {...props}\n >\n {children}\n <ChevronRightIcon className=\"ms-auto self-center text-[var(--ui-button-menu-dropdown-extras-cascade-icon-color)] rtl:rotate-180\" />\n </MenuPrimitive.SubmenuTrigger>\n));\nDropdownMenuSubTrigger.displayName = 'DropdownMenuSubTrigger';\n\n\nfunction DropdownMenuShortcut({\n className,\n ...props\n}: React.HTMLAttributes<HTMLSpanElement>) {\n return (\n <span\n className={cn('ms-auto shrink-0 text-sm font-normal leading-6 text-[var(--ui-button-menu-dropdown-extras-shortcut-label-color)]', className)}\n {...props}\n />\n );\n}\nDropdownMenuShortcut.displayName = 'DropdownMenuShortcut';\n\nconst DropdownMenuCheckboxItem = React.forwardRef<\n React.ElementRef<typeof MenuPrimitive.CheckboxItem>,\n React.ComponentPropsWithoutRef<typeof MenuPrimitive.CheckboxItem>\n>(({ className, children, ...props }, ref) => (\n <MenuPrimitive.CheckboxItem\n ref={ref}\n className={cn(itemClassName, className)}\n {...props}\n >\n <span className={indicatorSlotClassName}>\n <MenuPrimitive.CheckboxItemIndicator className=\"flex\">\n <CheckSmallIcon size={16} />\n </MenuPrimitive.CheckboxItemIndicator>\n </span>\n {children}\n </MenuPrimitive.CheckboxItem>\n));\nDropdownMenuCheckboxItem.displayName = 'DropdownMenuCheckboxItem';\n\nconst DropdownMenuRadioGroup = MenuPrimitive.RadioGroup;\n\nconst DropdownMenuRadioItem = React.forwardRef<\n React.ElementRef<typeof MenuPrimitive.RadioItem>,\n React.ComponentPropsWithoutRef<typeof MenuPrimitive.RadioItem>\n>(({ className, children, ...props }, ref) => (\n <MenuPrimitive.RadioItem\n ref={ref}\n className={cn(itemClassName, className)}\n {...props}\n >\n <span className={indicatorSlotClassName}>\n {/* The dot is the indicator element itself — Base UI renders it as a\n `<span>`, and an inline wrapper would collapse a sized child to 0. */}\n <MenuPrimitive.RadioItemIndicator className=\"block size-2 rounded-full bg-current\" />\n </span>\n {children}\n </MenuPrimitive.RadioItem>\n));\nDropdownMenuRadioItem.displayName = 'DropdownMenuRadioItem';\n\nconst DropdownMenuLabel = React.forwardRef<\n HTMLDivElement,\n React.HTMLAttributes<HTMLDivElement> & { inset?: boolean }\n>(({ className, inset, ...props }, ref) => (\n <div\n ref={ref}\n className={cn(\n 'px-[var(--ui-button-menu-dropdown-item-container-padding-x)] py-[var(--ui-button-menu-dropdown-item-container-padding-y)] text-sm font-semibold leading-6 text-[var(--ui-button-menu-dropdown-item-label-color)]',\n inset && indicatorInsetClassName,\n className\n )}\n {...props}\n />\n));\nDropdownMenuLabel.displayName = 'DropdownMenuLabel';\n\nconst DropdownMenuSeparator = React.forwardRef<\n HTMLDivElement,\n React.HTMLAttributes<HTMLDivElement>\n>(({ className, ...props }, ref) => (\n <div\n ref={ref}\n role=\"separator\"\n className={cn(\n 'my-[var(--ui-button-menu-dropdown-section-list-gap)] h-[var(--ui-button-menu-dropdown-section-container-border-width)] bg-[var(--ui-button-menu-dropdown-section-container-border-color)]',\n className\n )}\n {...props}\n />\n));\nDropdownMenuSeparator.displayName = 'DropdownMenuSeparator';\n\nexport {\n DropdownMenu,\n DropdownMenuTrigger,\n DropdownMenuContent,\n DropdownMenuGroup,\n DropdownMenuItem,\n DropdownMenuCheckboxItem,\n DropdownMenuRadioGroup,\n DropdownMenuRadioItem,\n DropdownMenuLabel,\n DropdownMenuSeparator,\n DropdownMenuShortcut,\n DropdownMenuSub,\n DropdownMenuSubContent,\n DropdownMenuSubTrigger,\n DropdownMenuPortal,\n};\n"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"input-num-picker.js","names":[],"sources":["../../../../src/components/ui/input-num-picker/input-num-picker.tsx"],"sourcesContent":["'use client';\n\nimport * as React from 'react';\nimport { NumberField as NumberFieldPrimitive } from '@base-ui/react/number-field';\nimport { MinusIcon, PlusIcon } from '@acronis-platform/icons-react/stroke-mono';\n\nimport { cn } from '@/lib/utils';\nimport { ButtonIconInput } from '../button-icon-input';\n\n// Mirrors the Figma \"InputNumPicker\" component: a numeric stepper field built on\n// Base UI's NumberField (Root/Group/Input/Decrement/Increment), themed by its own\n// `--ui-input-num-picker-*` tier. Adds the field furniture InputText/InputSelect\n// already ship: an optional `label` (with an optional `required` `*`). The stepper\n// buttons reuse `ButtonIconInput` (already themed for exactly this \"small icon\n// inside a field box\" role) via its `render` prop, rather than duplicating its\n// idle/hover/active/disabled token wiring here.\nexport interface InputNumPickerProps\n extends Omit<\n React.ComponentPropsWithoutRef<typeof NumberFieldPrimitive.Root>,\n 'children'\n > {\n /** Field label, rendered above the stepper box. */\n label?: React.ReactNode;\n /** Marks the field required — appends a `*` after the label. */\n required?: boolean;\n /** Accessible label for the decrement button. */\n decrementLabel?: string;\n /** Accessible label for the increment button. */\n incrementLabel?: string;\n}\n\nconst InputNumPicker = React.forwardRef<HTMLInputElement, InputNumPickerProps>(\n (\n {\n className,\n id,\n label,\n required,\n disabled,\n decrementLabel = 'Decrease',\n incrementLabel = 'Increase',\n ...props\n },\n ref\n ) => {\n const reactId = React.useId();\n const inputId = id ?? reactId;\n\n return (\n <NumberFieldPrimitive.Root\n id={inputId}\n disabled={disabled}\n required={required}\n className={cn(\n 'flex min-w-[var(--ui-input-num-picker-global-container-width-min)] flex-col items-center gap-[var(--ui-input-num-picker-global-container-gap)]',\n className\n )}\n {...props}\n >\n {label != null && label !== '' && (\n <label\n htmlFor={inputId}\n className={cn(\n 'flex w-full gap-[var(--ui-input-num-picker-global-container-label-gap)] text-sm leading-4',\n disabled\n ? 'text-[var(--ui-input-num-picker-global-label-color-disabled)]'\n : 'text-[var(--ui-input-num-picker-global-label-color-idle)]'\n )}\n >\n {label}\n {required && (\n <span\n aria-hidden=\"true\"\n className=\"text-[var(--ui-input-num-picker-global-required-color)]\"\n >\n *\n </span>\n )}\n </label>\n )}\n\n <NumberFieldPrimitive.Group\n className={cn(\n 'flex h-[var(--ui-input-num-picker-global-box-height)] w-full items-center gap-[var(--ui-input-num-picker-global-box-gap)] rounded-[var(--ui-input-num-picker-global-box-border-radius)] border-[length:var(--ui-input-num-picker-global-box-border-width)] border-solid border-[var(--ui-input-num-picker-normal-box-border-color-idle)] bg-[var(--ui-input-num-picker-global-box-color-idle)] px-[var(--ui-input-num-picker-global-box-padding-x)] py-[var(--ui-input-num-picker-global-box-padding-y)] transition-colors',\n 'not-has-disabled:hover:border-[var(--ui-input-num-picker-normal-box-border-color-hover)] not-has-disabled:hover:bg-[var(--ui-input-num-picker-global-box-color-hover)]',\n 'has-[input:focus-visible]:border-[var(--ui-input-num-picker-normal-box-border-color-hover)] has-[input:focus-visible]:ring-[3px] has-[input:focus-visible]:ring-[var(--ui-focus-primary)]',\n 'has-disabled:cursor-not-allowed has-disabled:border-[var(--ui-input-num-picker-normal-box-border-color-disabled)] has-disabled:bg-[var(--ui-input-num-picker-global-box-color-disabled)]'\n )}\n >\n <NumberFieldPrimitive.Decrement\n render={\n <ButtonIconInput aria-label={decrementLabel}>\n <MinusIcon size={16} />\n </ButtonIconInput>\n }\n />\n\n <NumberFieldPrimitive.Input\n ref={ref}\n className={cn(\n 'min-w-0 flex-1 bg-transparent text-center text-sm leading-6 outline-none',\n disabled\n ? 'text-[var(--ui-input-num-picker-global-value-color-disabled)]'\n : 'text-[var(--ui-input-num-picker-global-value-color-idle)]'\n )}\n />\n\n <NumberFieldPrimitive.Increment\n render={\n <ButtonIconInput aria-label={incrementLabel}>\n <PlusIcon size={16} />\n </ButtonIconInput>\n }\n />\n </NumberFieldPrimitive.Group>\n </NumberFieldPrimitive.Root>\n );\n }\n);\nInputNumPicker.displayName = 'InputNumPicker';\n\nexport { InputNumPicker };\n"],"mappings":";;;;;;;;AA+BA,IAAM,IAAiB,EAAM,YAEzB,EACE,cACA,OACA,UACA,aACA,aACA,oBAAiB,YACjB,oBAAiB,YACjB,GAAG,KAEL,MACG;CACH,IAAM,IAAU,EAAM,MAAM,GACtB,IAAU,KAAM;CAEtB,OACE,kBAAC,EAAqB,MAAtB;EACE,IAAI;EACM;EACA;EACV,WAAW,EACT,kJACA,CACF;EACA,GAAI;EARN,UAAA,CAUG,KAAS,QAAQ,MAAU,MAC1B,kBAAC,SAAD;GACE,SAAS;GACT,WAAW,EACT,6FACA,IACI,kEACA,2DACN;GAPF,UAAA,CASG,GACA,KACC,kBAAC,QAAD;IACE,eAAY;IACZ,WAAU;IACX,UAAA;GAEK,CAAA,CAEH;EAGT,CAAA,GAAA,kBAAC,EAAqB,OAAtB;GACE,WAAW,EACT,8fACA,0KACA,6LACA,0LACF;GANF,UAAA;IAQE,kBAAC,EAAqB,WAAtB,EACE,QACE,kBAAC,GAAD;KAAiB,cAAY;
|
|
1
|
+
{"version":3,"file":"input-num-picker.js","names":[],"sources":["../../../../src/components/ui/input-num-picker/input-num-picker.tsx"],"sourcesContent":["'use client';\n\nimport * as React from 'react';\nimport { NumberField as NumberFieldPrimitive } from '@base-ui/react/number-field';\nimport { MinusIcon, PlusIcon } from '@acronis-platform/icons-react/stroke-mono';\n\nimport { cn } from '@/lib/utils';\nimport { ButtonIconInput } from '../button-icon-input';\n\n// Mirrors the Figma \"InputNumPicker\" component: a numeric stepper field built on\n// Base UI's NumberField (Root/Group/Input/Decrement/Increment), themed by its own\n// `--ui-input-num-picker-*` tier. Adds the field furniture InputText/InputSelect\n// already ship: an optional `label` (with an optional `required` `*`). The stepper\n// buttons reuse `ButtonIconInput` (already themed for exactly this \"small icon\n// inside a field box\" role) via its `render` prop, rather than duplicating its\n// idle/hover/active/disabled token wiring here.\nexport interface InputNumPickerProps\n extends Omit<\n React.ComponentPropsWithoutRef<typeof NumberFieldPrimitive.Root>,\n 'children'\n > {\n /** Field label, rendered above the stepper box. */\n label?: React.ReactNode;\n /** Marks the field required — appends a `*` after the label. */\n required?: boolean;\n /** Accessible label for the decrement button. */\n decrementLabel?: string;\n /** Accessible label for the increment button. */\n incrementLabel?: string;\n}\n\nconst InputNumPicker = React.forwardRef<HTMLInputElement, InputNumPickerProps>(\n (\n {\n className,\n id,\n label,\n required,\n disabled,\n decrementLabel = 'Decrease',\n incrementLabel = 'Increase',\n ...props\n },\n ref\n ) => {\n const reactId = React.useId();\n const inputId = id ?? reactId;\n\n return (\n <NumberFieldPrimitive.Root\n id={inputId}\n disabled={disabled}\n required={required}\n className={cn(\n 'flex min-w-[var(--ui-input-num-picker-global-container-width-min)] flex-col items-center gap-[var(--ui-input-num-picker-global-container-gap)]',\n className\n )}\n {...props}\n >\n {label != null && label !== '' && (\n <label\n htmlFor={inputId}\n className={cn(\n 'flex w-full gap-[var(--ui-input-num-picker-global-container-label-gap)] text-sm leading-4',\n disabled\n ? 'text-[var(--ui-input-num-picker-global-label-color-disabled)]'\n : 'text-[var(--ui-input-num-picker-global-label-color-idle)]'\n )}\n >\n {label}\n {required && (\n <span\n aria-hidden=\"true\"\n className=\"text-[var(--ui-input-num-picker-global-required-color)]\"\n >\n *\n </span>\n )}\n </label>\n )}\n\n <NumberFieldPrimitive.Group\n className={cn(\n 'flex h-[var(--ui-input-num-picker-global-box-height)] w-full items-center gap-[var(--ui-input-num-picker-global-box-gap)] rounded-[var(--ui-input-num-picker-global-box-border-radius)] border-[length:var(--ui-input-num-picker-global-box-border-width)] border-solid border-[var(--ui-input-num-picker-normal-box-border-color-idle)] bg-[var(--ui-input-num-picker-global-box-color-idle)] px-[var(--ui-input-num-picker-global-box-padding-x)] py-[var(--ui-input-num-picker-global-box-padding-y)] transition-colors',\n 'not-has-disabled:hover:border-[var(--ui-input-num-picker-normal-box-border-color-hover)] not-has-disabled:hover:bg-[var(--ui-input-num-picker-global-box-color-hover)]',\n 'has-[input:focus-visible]:border-[var(--ui-input-num-picker-normal-box-border-color-hover)] has-[input:focus-visible]:ring-[3px] has-[input:focus-visible]:ring-[var(--ui-focus-primary)]',\n 'has-disabled:cursor-not-allowed has-disabled:border-[var(--ui-input-num-picker-normal-box-border-color-disabled)] has-disabled:bg-[var(--ui-input-num-picker-global-box-color-disabled)]'\n )}\n >\n <NumberFieldPrimitive.Decrement\n render={\n <ButtonIconInput aria-label={decrementLabel}>\n {/* Full-size glyph swapped for a small variant in Checkbox/Combobox/InputSelect/DropdownMenu's selection-indicator role; this is a decrement affordance, not a selection indicator, so it stays until design rules on whether the inset glyph applies here too. */}\n <MinusIcon size={16} />\n </ButtonIconInput>\n }\n />\n\n <NumberFieldPrimitive.Input\n ref={ref}\n className={cn(\n 'min-w-0 flex-1 bg-transparent text-center text-sm leading-6 outline-none',\n disabled\n ? 'text-[var(--ui-input-num-picker-global-value-color-disabled)]'\n : 'text-[var(--ui-input-num-picker-global-value-color-idle)]'\n )}\n />\n\n <NumberFieldPrimitive.Increment\n render={\n <ButtonIconInput aria-label={incrementLabel}>\n <PlusIcon size={16} />\n </ButtonIconInput>\n }\n />\n </NumberFieldPrimitive.Group>\n </NumberFieldPrimitive.Root>\n );\n }\n);\nInputNumPicker.displayName = 'InputNumPicker';\n\nexport { InputNumPicker };\n"],"mappings":";;;;;;;;AA+BA,IAAM,IAAiB,EAAM,YAEzB,EACE,cACA,OACA,UACA,aACA,aACA,oBAAiB,YACjB,oBAAiB,YACjB,GAAG,KAEL,MACG;CACH,IAAM,IAAU,EAAM,MAAM,GACtB,IAAU,KAAM;CAEtB,OACE,kBAAC,EAAqB,MAAtB;EACE,IAAI;EACM;EACA;EACV,WAAW,EACT,kJACA,CACF;EACA,GAAI;EARN,UAAA,CAUG,KAAS,QAAQ,MAAU,MAC1B,kBAAC,SAAD;GACE,SAAS;GACT,WAAW,EACT,6FACA,IACI,kEACA,2DACN;GAPF,UAAA,CASG,GACA,KACC,kBAAC,QAAD;IACE,eAAY;IACZ,WAAU;IACX,UAAA;GAEK,CAAA,CAEH;EAGT,CAAA,GAAA,kBAAC,EAAqB,OAAtB;GACE,WAAW,EACT,8fACA,0KACA,6LACA,0LACF;GANF,UAAA;IAQE,kBAAC,EAAqB,WAAtB,EACE,QACE,kBAAC,GAAD;KAAiB,cAAY;KAE3B,UAAA,kBAAC,GAAD,EAAW,MAAM,GAAK,CAAA;IACP,CAAA,EAEpB,CAAA;IAED,kBAAC,EAAqB,OAAtB;KACO;KACL,WAAW,EACT,4EACA,IACI,kEACA,2DACN;IACD,CAAA;IAED,kBAAC,EAAqB,WAAtB,EACE,QACE,kBAAC,GAAD;KAAiB,cAAY;KAC3B,UAAA,kBAAC,GAAD,EAAU,MAAM,GAAK,CAAA;IACN,CAAA,EAEpB,CAAA;GACyB;EACH,CAAA,CAAA;;AAE/B,CACF;AACA,EAAe,cAAc"}
|
|
@@ -2,7 +2,7 @@ import { cn as e } from "../../../lib/utils.js";
|
|
|
2
2
|
import { usePortalContainer as t } from "../../../lib/portal-container.js";
|
|
3
3
|
import * as n from "react";
|
|
4
4
|
import { jsx as r, jsxs as i } from "react/jsx-runtime";
|
|
5
|
-
import {
|
|
5
|
+
import { CheckSmallIcon as a, ChevronDownIcon as o, ChevronRightIcon as s, CircleWarningIcon as c, InboxIcon as l, MagnifierIcon as u } from "@acronis-platform/icons-react/stroke-mono";
|
|
6
6
|
import { Select as d } from "@base-ui/react/select";
|
|
7
7
|
//#region src/components/ui/input-select/input-select.tsx
|
|
8
8
|
var f = n.createContext(!1), p = n.createContext(null);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"input-select.js","names":[],"sources":["../../../../src/components/ui/input-select/input-select.tsx"],"sourcesContent":["import * as React from 'react';\nimport { Select as SelectPrimitive } from '@base-ui/react/select';\nimport {\n CheckIcon,\n ChevronDownIcon,\n ChevronRightIcon,\n CircleWarningIcon,\n InboxIcon,\n MagnifierIcon,\n} from '@acronis-platform/icons-react/stroke-mono';\n\nimport { cn } from '@/lib/utils';\nimport { usePortalContainer } from '@/lib/portal-container';\n\n// The next-gen select, themed by the dedicated `--ui-input-select-*` tier (global /\n// normal / error / dropdown). It composes Base UI `Select` and adds the field\n// furniture (label, required, description, error) and the dropdown machinery\n// (in-dropdown search, sections/groups, single + multiple items, loading/empty/error\n// status). The trigger box wires each state to its own token — idle / hover / open\n// (`data-popup-open`) + focus ring / disabled — and switches to the error border +\n// `--ui-focus-error` ring when `aria-invalid` is set. Selection mode (single vs\n// multiple) flows from the `multiple` prop on the root via `InputSelectModeContext`:\n// single items toggle the row background and show a trailing check; multiple items\n// keep the row background and show a leading checkbox.\n\nconst InputSelectModeContext = React.createContext(false);\n\ninterface InputSelectFilterContextValue {\n /** Current in-dropdown search query. */\n query: string;\n /** Update the search query. */\n setQuery: (query: string) => void;\n}\n\nconst InputSelectFilterContext =\n React.createContext<InputSelectFilterContextValue | null>(null);\n\n/**\n * Read the live in-dropdown search query (and its setter) from the nearest\n * `InputSelect`. Flat item lists filter themselves; use this for hierarchical\n * (tree) dropdowns that need to compute their own visibility.\n */\nfunction useInputSelectFilter(): InputSelectFilterContextValue {\n const context = React.useContext(InputSelectFilterContext);\n if (!context) {\n throw new Error('useInputSelectFilter must be used within <InputSelect>.');\n }\n return context;\n}\n\nfunction InputSelect<Value, Multiple extends boolean | undefined = false>(\n props: SelectPrimitive.Root.Props<Value, Multiple>\n) {\n const { onOpenChange } = props;\n const [query, setQuery] = React.useState('');\n const filter = React.useMemo(() => ({ query, setQuery }), [query]);\n\n // Reset the query when the popup closes so it reopens unfiltered, via two paths.\n // 1. `onOpenChange` — the only path in uncontrolled mode, where Base UI owns the\n // open state and reports every real transition. A consumer that calls\n // `eventDetails.cancel()` keeps the popup open (Base UI skips its own state\n // update too), so the query must survive that.\n // 2. The `open` prop transitioning true -> false — needed in controlled mode,\n // where a consumer can flip its own state directly (e.g. an external toggle\n // button whose click handler runs after it cancelled Base UI's outside-press\n // close) without `onOpenChange` ever firing for that transition. A cancelled\n // close leaves `open` at `true`, so this path preserves the query too.\n const handleOpenChange = React.useCallback<\n NonNullable<SelectPrimitive.Root.Props<Value, Multiple>['onOpenChange']>\n >(\n (open, eventDetails) => {\n onOpenChange?.(open, eventDetails);\n if (!open && !eventDetails.isCanceled) {\n setQuery('');\n }\n },\n [onOpenChange]\n );\n\n const controlledOpen = props.open;\n const previousOpenRef = React.useRef(controlledOpen);\n React.useEffect(() => {\n if (previousOpenRef.current && controlledOpen === false) {\n setQuery('');\n }\n previousOpenRef.current = controlledOpen;\n }, [controlledOpen]);\n\n return (\n <InputSelectModeContext.Provider value={Boolean(props.multiple)}>\n <InputSelectFilterContext.Provider value={filter}>\n <SelectPrimitive.Root {...props} onOpenChange={handleOpenChange} />\n </InputSelectFilterContext.Provider>\n </InputSelectModeContext.Provider>\n );\n}\nInputSelect.displayName = 'InputSelect';\n\nconst InputSelectGroup = SelectPrimitive.Group;\n\n/** Vertical field stack: label, trigger, description/error. */\nconst InputSelectField = React.forwardRef<\n HTMLDivElement,\n React.ComponentPropsWithoutRef<'div'>\n>(({ className, ...props }, ref) => (\n <div\n ref={ref}\n className={cn(\n 'flex min-w-[var(--ui-input-select-global-container-width-min)] flex-col gap-[var(--ui-input-select-global-container-gap)]',\n className\n )}\n {...props}\n />\n));\nInputSelectField.displayName = 'InputSelectField';\n\nconst InputSelectLabel = React.forwardRef<\n React.ElementRef<typeof SelectPrimitive.Label>,\n React.ComponentPropsWithoutRef<typeof SelectPrimitive.Label> & {\n /** Appends a required `*` after the label text. */\n required?: boolean;\n }\n>(({ className, children, required, ...props }, ref) => (\n <SelectPrimitive.Label\n ref={ref}\n className={cn(\n 'flex gap-[var(--ui-input-select-global-container-label-gap)] text-sm leading-4 text-[var(--ui-input-select-global-label-color-idle)] data-[disabled]:text-[var(--ui-input-select-global-label-color-disabled)]',\n className\n )}\n {...props}\n >\n {children}\n {required && (\n <span\n aria-hidden=\"true\"\n className=\"text-[var(--ui-input-select-global-required-color)]\"\n >\n *\n </span>\n )}\n </SelectPrimitive.Label>\n));\nInputSelectLabel.displayName = 'InputSelectLabel';\n\nconst InputSelectTrigger = React.forwardRef<\n React.ElementRef<typeof SelectPrimitive.Trigger>,\n React.ComponentPropsWithoutRef<typeof SelectPrimitive.Trigger>\n>(({ className, children, ...props }, ref) => (\n <SelectPrimitive.Trigger\n ref={ref}\n className={cn(\n 'group flex h-[var(--ui-input-select-global-box-height)] w-full min-w-0 items-center gap-[var(--ui-input-select-global-box-gap)] rounded-[var(--ui-input-select-global-box-border-radius)] border bg-[var(--ui-input-select-global-box-color-idle)] border-[var(--ui-input-select-normal-box-border-color-idle)] px-[var(--ui-input-select-global-box-padding-x)] text-sm leading-6 text-[var(--ui-input-select-global-value-color-idle)] outline-none transition-colors',\n 'not-data-[disabled]:hover:bg-[var(--ui-input-select-global-box-color-hover)] not-data-[disabled]:hover:border-[var(--ui-input-select-normal-box-border-color-hover)]',\n 'focus-visible:border-[var(--ui-input-select-normal-box-border-color-hover)] focus-visible:ring-[3px] focus-visible:ring-[var(--ui-focus-primary)]',\n 'data-[popup-open]:border-[var(--ui-input-select-normal-box-border-color-hover)] data-[popup-open]:ring-[3px] data-[popup-open]:ring-[var(--ui-focus-primary)]',\n 'data-[disabled]:cursor-not-allowed data-[disabled]:border-[var(--ui-input-select-normal-box-border-color-disabled)] data-[disabled]:bg-[var(--ui-input-select-global-box-color-disabled)] data-[disabled]:text-[var(--ui-input-select-global-value-color-disabled)]',\n // Error treatment (driven by `aria-invalid`).\n 'aria-invalid:border-[var(--ui-input-select-error-box-border-color-idle)] not-data-[disabled]:aria-invalid:hover:border-[var(--ui-input-select-error-box-border-color-hover)] aria-invalid:focus-visible:border-[var(--ui-input-select-error-box-border-color-hover)] aria-invalid:focus-visible:ring-[var(--ui-focus-error)] aria-invalid:data-[popup-open]:border-[var(--ui-input-select-error-box-border-color-hover)] aria-invalid:data-[popup-open]:ring-[var(--ui-focus-error)]',\n className\n )}\n {...props}\n >\n {children}\n <SelectPrimitive.Icon className=\"flex size-[var(--ui-input-select-global-icon-box-size)] shrink-0 items-center justify-center text-[var(--ui-input-select-normal-icon-expand-color-idle)] group-data-[disabled]:text-[var(--ui-input-select-normal-icon-expand-color-disabled)]\">\n <ChevronDownIcon\n size={16}\n className=\"transition-transform group-data-[popup-open]:rotate-180\"\n />\n </SelectPrimitive.Icon>\n </SelectPrimitive.Trigger>\n));\nInputSelectTrigger.displayName = 'InputSelectTrigger';\n\nconst InputSelectValue = React.forwardRef<\n React.ElementRef<typeof SelectPrimitive.Value>,\n React.ComponentPropsWithoutRef<typeof SelectPrimitive.Value>\n>(({ className, ...props }, ref) => (\n <SelectPrimitive.Value\n ref={ref}\n className={cn(\n 'min-w-0 flex-1 truncate text-start text-[var(--ui-input-select-global-value-color-idle)] data-[placeholder]:text-[var(--ui-input-select-global-placeholder-color-idle)]',\n 'group-data-[disabled]:!text-[var(--ui-input-select-global-value-color-disabled)] group-data-[disabled]:data-[placeholder]:!text-[var(--ui-input-select-global-placeholder-color-disabled)]',\n className\n )}\n {...props}\n />\n));\nInputSelectValue.displayName = 'InputSelectValue';\n\nconst InputSelectContent = React.forwardRef<\n React.ElementRef<typeof SelectPrimitive.Popup>,\n React.ComponentPropsWithoutRef<typeof SelectPrimitive.Popup> & {\n sideOffset?: number;\n align?: SelectPrimitive.Positioner.Props['align'];\n side?: SelectPrimitive.Positioner.Props['side'];\n /**\n * Offset in px along the alignment axis (perpendicular to `side`). Defaults\n * to Base UI's own `0` when omitted — pass a value to nudge the dropdown\n * along the trigger's edge without changing its `align`.\n */\n alignOffset?: SelectPrimitive.Positioner.Props['alignOffset'];\n /**\n * Collision-avoidance strategy. Defaults to Base UI's own flip/shift\n * behavior, which may move the dropdown off the requested `side`/`align`\n * when it doesn't fit. Pass `{ side: 'none', fallbackAxisSide: 'none' }`\n * alongside an explicit `side`/`align` to lock the popup to that placement\n * with no auto-flip fallback (e.g. \"always to the right, no matter what\":\n * `side=\"right\" sideOffset={20} collisionAvoidance={{ side: 'none',\n * fallbackAxisSide: 'none' }}`).\n */\n collisionAvoidance?: SelectPrimitive.Positioner.Props['collisionAvoidance'];\n /**\n * Element (or ref/getter) the popup positions itself against, overriding\n * the default of anchoring to `InputSelectTrigger`. Use when the visible\n * trigger isn't the element Base UI tracks internally — e.g. an external\n * button drives a hidden trigger, and the popup should align with the\n * button instead of the hidden trigger's layout position.\n */\n anchor?: SelectPrimitive.Positioner.Props['anchor'];\n /**\n * Container to portal the dropdown into. Defaults to the nearest\n * `PortalContainerProvider`, or `document.body` when there is none; pass an\n * element to scope the portal explicitly (e.g. a shadow root, so the popup\n * inherits styles defined there).\n */\n portalContainer?: SelectPrimitive.Portal.Props['container'];\n /**\n * Render the dropdown chrome like `PopoverContent` (`--ui-popover-container-*`\n * tokens, no shadow, fade/zoom/slide enter-exit animation) instead of the\n * default `--ui-input-select-dropdown-container-*` tokens + static `shadow-md`.\n * See `components/ui/popover/popover.tsx`.\n */\n isPopoverStyled?: boolean;\n }\n>(\n (\n {\n className,\n children,\n sideOffset = 4,\n align = 'start',\n side = 'bottom',\n alignOffset,\n collisionAvoidance,\n anchor,\n portalContainer,\n isPopoverStyled = false,\n ...props\n },\n ref\n ) => {\n const ctxContainer = usePortalContainer();\n const resolvedContainer = portalContainer ?? ctxContainer;\n\n return (\n <SelectPrimitive.Portal container={resolvedContainer}>\n <SelectPrimitive.Positioner\n sideOffset={sideOffset}\n align={align}\n side={side}\n alignOffset={alignOffset}\n collisionAvoidance={collisionAvoidance}\n anchor={anchor}\n alignItemWithTrigger={false}\n className=\"z-50 outline-none\"\n >\n <SelectPrimitive.Popup\n ref={ref}\n className={cn(\n 'max-h-[var(--available-height)] min-w-[var(--anchor-width)] overflow-y-auto py-[var(--ui-input-select-dropdown-container-padding-y)] text-sm outline-none',\n // Keep the border/radius/background token references and the animation\n // classes below in sync with PopoverContent's container in popover.tsx —\n // but deliberately NOT its sizing (`min-w`/`max-w`) or `text-foreground`:\n // the dropdown keeps its own `--anchor-width`/`--available-height` sizing\n // and default text color whether or not `isPopoverStyled` is set.\n isPopoverStyled\n ? [\n 'rounded-[var(--ui-popover-container-border-radius)] border-[length:var(--ui-popover-container-border-width)] border-solid border-[var(--ui-popover-container-border-color)] bg-[var(--ui-popover-container-color)]',\n 'duration-200 data-[open]:animate-in data-[closed]:animate-out data-[open]:fade-in-0 data-[closed]:fade-out-0 data-[open]:zoom-in-95 data-[closed]:zoom-out-95',\n 'data-[side=bottom]:slide-in-from-top-2 data-[side=top]:slide-in-from-bottom-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2',\n ]\n : 'rounded-[var(--ui-input-select-dropdown-container-border-radius)] border border-[var(--ui-input-select-dropdown-container-border-color)] bg-[var(--ui-input-select-dropdown-container-color)] shadow-md',\n className\n )}\n {...props}\n >\n {children}\n </SelectPrimitive.Popup>\n </SelectPrimitive.Positioner>\n </SelectPrimitive.Portal>\n );\n }\n);\nInputSelectContent.displayName = 'InputSelectContent';\n\n/**\n * In-dropdown search row (magnifier + input). By default it drives the\n * `InputSelect` filter context — flat `InputSelectItem`s filter themselves, and\n * tree dropdowns read the query via `useInputSelectFilter`. Pass `value`/`onChange`\n * to control the query externally.\n */\nconst InputSelectSearch = React.forwardRef<\n HTMLInputElement,\n React.ComponentPropsWithoutRef<'input'>\n>(({ className, value, onChange, onKeyDown, ...props }, ref) => {\n const filter = React.useContext(InputSelectFilterContext);\n const setQuery = filter?.setQuery;\n const controlled = value !== undefined;\n\n // When the query is controlled externally, the consumer's `value` is the\n // source of truth for what's displayed, so keep the internal filter context\n // (what flat items match against) synced to it. A prop-driven value change —\n // a \"clear\" button resetting to '', a debounced/transformed value — doesn't\n // fire `onChange`, so driving the filter off raw DOM events alone would leave\n // `filter.query` stale and hide every item against a query the box no longer\n // shows. `setQuery` is a stable state setter, so this runs only when `value`\n // changes.\n React.useEffect(() => {\n if (controlled) {\n setQuery?.(String(value ?? ''));\n }\n }, [controlled, value, setQuery]);\n\n return (\n <div className=\"flex items-center gap-[var(--ui-input-select-dropdown-dropdown-search-gap)] px-[var(--ui-input-select-dropdown-dropdown-search-padding-x)] py-[var(--ui-input-select-dropdown-dropdown-search-padding-y)]\">\n <MagnifierIcon\n size={16}\n className=\"shrink-0 text-[var(--ui-glyph-on-surface-primary)]\"\n />\n <input\n ref={ref}\n type=\"search\"\n value={value ?? filter?.query ?? ''}\n onChange={(event) => {\n onChange?.(event);\n // Uncontrolled: the input's value *is* the filter query, so write it\n // straight through. Controlled: the effect above syncs the filter to\n // the consumer's `value` once it re-renders, avoiding a flash of raw\n // typed text when the consumer debounces or transforms the value.\n if (!controlled) {\n filter?.setQuery(event.currentTarget.value);\n }\n }}\n // Base UI Select's typeahead would consume printable keys before they\n // reach this input, so stop those from bubbling — but let navigation and\n // selection keys (Arrow*/Home/End/Enter/Escape, all multi-char `key`\n // names) through so the user can move from the search box into the\n // filtered list and pick a result with the keyboard.\n onKeyDown={(event) => {\n onKeyDown?.(event);\n if (event.key.length === 1) {\n event.stopPropagation();\n }\n }}\n className={cn(\n 'min-w-0 flex-1 border-0 bg-transparent p-0 text-sm leading-6 text-[var(--ui-input-select-dropdown-dropdown-search-label-color-value)] outline-none placeholder:text-[var(--ui-input-select-dropdown-dropdown-search-label-color-placeholder)] [&::-webkit-search-cancel-button]:appearance-none',\n className\n )}\n {...props}\n />\n </div>\n );\n});\nInputSelectSearch.displayName = 'InputSelectSearch';\n\n/** A section (group) of items with an optional header. Divided by a top border. */\nconst InputSelectSection = React.forwardRef<\n React.ElementRef<typeof SelectPrimitive.Group>,\n React.ComponentPropsWithoutRef<typeof SelectPrimitive.Group>\n>(({ className, ...props }, ref) => (\n <SelectPrimitive.Group\n ref={ref}\n className={cn(\n 'flex flex-col border-t border-[var(--ui-input-select-dropdown-section-container-border-color)] py-[var(--ui-input-select-dropdown-section-container-padding-y)] first:border-t-0',\n className\n )}\n {...props}\n />\n));\nInputSelectSection.displayName = 'InputSelectSection';\n\nconst InputSelectSectionLabel = React.forwardRef<\n React.ElementRef<typeof SelectPrimitive.GroupLabel>,\n React.ComponentPropsWithoutRef<typeof SelectPrimitive.GroupLabel>\n>(({ className, ...props }, ref) => (\n <SelectPrimitive.GroupLabel\n ref={ref}\n className={cn(\n 'px-[var(--ui-input-select-dropdown-section-container-header-padding-x)] py-[var(--ui-input-select-dropdown-section-container-header-padding-y)] text-sm font-semibold leading-6 text-[var(--ui-input-select-dropdown-section-label-group-color)]',\n className\n )}\n {...props}\n />\n));\nInputSelectSectionLabel.displayName = 'InputSelectSectionLabel';\n\n/**\n * Width (px) of the leading nesting spacer for a 1-based tree `indent` level, per\n * the Figma \"InputSelectDropdownTenants\" spec: level 1 reserves 16 px (enough for a\n * single chevron) and each deeper level adds 24 px — 16 / 40 / 64 for levels 1–3.\n * The tenant icon therefore starts at the same x-position whether or not the row is\n * expandable, because the chevron lives right-aligned inside this reserved space.\n */\nconst NESTING_BASE = 16;\nconst NESTING_STEP = 24;\nfunction nestingWidth(indent: number): number {\n return NESTING_BASE + (indent - 1) * NESTING_STEP;\n}\n\nexport interface InputSelectItemProps\n extends React.ComponentPropsWithoutRef<typeof SelectPrimitive.Item> {\n /** Optional leading icon rendered before the label text. Colored by `--ui-input-select-dropdown-item-global-icon-tenant`. */\n icon?: React.ReactNode;\n /** 1-based nesting level (0 / omitted = no indent). Levels 1–3 reserve 16 / 40 / 64 px. */\n indent?: number;\n /**\n * Text used to match the in-dropdown search query. Defaults to the string\n * `children`. When a query is active and this text doesn't match, the row hides\n * itself — unless `hidden` is passed explicitly (tree dropdowns compute their own\n * visibility). Rows stay mounted while hidden to keep Base UI's selection index\n * stable.\n */\n textValue?: string;\n}\n\nconst InputSelectItem = React.forwardRef<\n React.ElementRef<typeof SelectPrimitive.Item>,\n InputSelectItemProps\n>(({ className, children, icon, indent, textValue, hidden, ...props }, ref) => {\n const multiple = React.useContext(InputSelectModeContext);\n const filter = React.useContext(InputSelectFilterContext);\n const query = filter?.query.trim().toLowerCase() ?? '';\n const label = textValue ?? (typeof children === 'string' ? children : undefined);\n const autoHidden =\n query.length > 0 && label !== undefined && !label.toLowerCase().includes(query);\n return (\n <SelectPrimitive.Item\n ref={ref}\n hidden={hidden ?? autoHidden}\n className={cn(\n 'group/item relative flex cursor-default items-center gap-[var(--ui-input-select-dropdown-item-global-container-gap)] px-[var(--ui-input-select-dropdown-item-global-container-padding-x)] py-[var(--ui-input-select-dropdown-item-global-container-padding-y)] leading-6 text-[var(--ui-input-select-dropdown-item-global-label-color)] outline-none select-none',\n 'bg-[var(--ui-input-select-dropdown-item-unselected-container-color-idle)] data-[highlighted]:bg-[var(--ui-input-select-dropdown-item-unselected-container-color-hover)]',\n // Single-select rows tint when selected; multiple-select rows keep the\n // unselected background (the leading checkbox carries the state).\n !multiple &&\n 'data-[selected]:bg-[var(--ui-input-select-dropdown-item-selected-container-color-idle)] data-[selected]:data-[highlighted]:bg-[var(--ui-input-select-dropdown-item-selected-container-color-hover)]',\n 'data-[disabled]:pointer-events-none data-[disabled]:bg-[var(--ui-input-select-dropdown-item-unselected-container-color-disabled)]',\n className\n )}\n {...props}\n >\n {multiple && (\n <span\n aria-hidden=\"true\"\n className=\"flex size-[var(--ui-checkbox-global-box-size)] shrink-0 items-center justify-center rounded-[var(--ui-checkbox-global-box-border-radius)] border-[length:var(--ui-checkbox-global-box-border-width)] border-[var(--ui-checkbox-unchecked-box-border-color-idle)] bg-[var(--ui-checkbox-unchecked-box-color-idle)] text-transparent group-data-[selected]/item:border-[var(--ui-checkbox-checked-box-border-color-idle)] group-data-[selected]/item:bg-[var(--ui-checkbox-checked-box-color-idle)] group-data-[selected]/item:text-[var(--ui-checkbox-checked-icon-color-idle)]\"\n >\n <CheckIcon size={16} />\n </span>\n )}\n {typeof indent === 'number' && indent > 0 && (\n <span\n aria-hidden=\"true\"\n className=\"size-4 shrink-0\"\n style={{ minWidth: nestingWidth(indent) }}\n />\n )}\n {icon && (\n <span className=\"flex shrink-0 items-center text-[var(--ui-input-select-dropdown-item-global-icon-tenant)]\">\n {icon}\n </span>\n )}\n <SelectPrimitive.ItemText className=\"min-w-0 flex-1 truncate\">\n {children}\n </SelectPrimitive.ItemText>\n {!multiple && (\n <SelectPrimitive.ItemIndicator className=\"flex shrink-0 items-center text-[var(--ui-input-select-dropdown-item-global-icon-checked)]\">\n <CheckIcon size={16} />\n </SelectPrimitive.ItemIndicator>\n )}\n </SelectPrimitive.Item>\n );\n});\nInputSelectItem.displayName = 'InputSelectItem';\n\nexport interface InputSelectExpanderProps\n extends React.ComponentPropsWithoutRef<'button'> {\n /** Whether the group is currently expanded. */\n expanded: boolean;\n /** Called when the user clicks the row to toggle expand/collapse. */\n onToggle: () => void;\n /** Optional leading icon rendered after the chevron. */\n icon?: React.ReactNode;\n /** 1-based nesting level (0 / omitted = level 1). Levels 1–3 reserve 16 / 40 / 64 px; the chevron sits right-aligned inside. */\n indent?: number;\n}\n\n/**\n * A non-selectable row that acts as an expand/collapse toggle for a tree group.\n * Visually identical to `InputSelectItem` but is **not** a `SelectPrimitive.Item`,\n * so clicking it won't set the select value.\n *\n * When collapsing a group, keep its child `InputSelectItem`s mounted and toggle\n * their `hidden` prop rather than unmounting them: Base UI's Select tracks the\n * selection by list index, so removing the selected row from the DOM makes a\n * sibling inherit its index and render a phantom check. `hidden` rows keep the\n * indices stable and are skipped by keyboard navigation.\n */\nconst InputSelectExpander = React.forwardRef<\n HTMLButtonElement,\n InputSelectExpanderProps\n>(({ className, children, expanded, onToggle, icon, indent, ...props }, ref) => (\n <button\n ref={ref}\n type=\"button\"\n onClick={onToggle}\n aria-expanded={expanded}\n className={cn(\n 'group/item relative flex w-full cursor-default items-center gap-[var(--ui-input-select-dropdown-item-global-container-gap)] px-[var(--ui-input-select-dropdown-item-global-container-padding-x)] py-[var(--ui-input-select-dropdown-item-global-container-padding-y)] text-start leading-6 text-[var(--ui-input-select-dropdown-item-global-label-color)] outline-none select-none',\n 'bg-[var(--ui-input-select-dropdown-item-unselected-container-color-idle)] hover:bg-[var(--ui-input-select-dropdown-item-unselected-container-color-hover)]',\n className\n )}\n {...props}\n >\n <span\n aria-hidden=\"true\"\n className=\"flex shrink-0 items-center justify-end text-[var(--ui-input-select-dropdown-item-global-icon-collapse)]\"\n style={{\n minWidth:\n typeof indent === 'number' && indent > 0 ? nestingWidth(indent) : NESTING_BASE,\n }}\n >\n {expanded ? <ChevronDownIcon size={16} /> : <ChevronRightIcon size={16} />}\n </span>\n {icon && (\n <span className=\"flex shrink-0 items-center text-[var(--ui-input-select-dropdown-item-global-icon-tenant)]\">\n {icon}\n </span>\n )}\n <span className=\"min-w-0 flex-1 truncate\">{children}</span>\n </button>\n));\nInputSelectExpander.displayName = 'InputSelectExpander';\n\nconst InputSelectDescription = React.forwardRef<\n HTMLParagraphElement,\n React.ComponentPropsWithoutRef<'p'>\n>(({ className, ...props }, ref) => (\n <p\n ref={ref}\n className={cn(\n 'text-xs leading-4 text-[var(--ui-input-select-normal-description-color-idle)]',\n className\n )}\n {...props}\n />\n));\nInputSelectDescription.displayName = 'InputSelectDescription';\n\nconst InputSelectError = React.forwardRef<\n HTMLParagraphElement,\n React.ComponentPropsWithoutRef<'p'>\n>(({ className, ...props }, ref) => (\n <p\n ref={ref}\n className={cn(\n 'text-xs leading-4 text-[var(--ui-input-select-error-error-msg-color)]',\n className\n )}\n {...props}\n />\n));\nInputSelectError.displayName = 'InputSelectError';\n\nexport interface InputSelectStatusProps\n extends React.ComponentPropsWithoutRef<'div'> {\n /** Which status to show. Drives the leading icon. */\n variant: 'loading' | 'empty' | 'error';\n /** Optional trailing action (e.g. a \"Try again\" button) — shown for `error`. */\n action?: React.ReactNode;\n}\n\n/** Loading / empty / error status row shown instead of items inside the dropdown. */\nconst InputSelectStatus = React.forwardRef<HTMLDivElement, InputSelectStatusProps>(\n ({ className, variant, children, action, ...props }, ref) => (\n <div\n ref={ref}\n className={cn(\n 'flex min-h-[var(--ui-input-select-dropdown-container-status-width-min)] flex-col items-center justify-center gap-[var(--ui-input-select-dropdown-container-status-gap)] border-t border-[var(--ui-input-select-dropdown-section-container-border-color)] px-[var(--ui-input-select-dropdown-container-status-padding-x)] py-[var(--ui-input-select-dropdown-container-status-padding-y)] text-center text-sm leading-6 text-[var(--ui-input-select-dropdown-item-global-label-color)]',\n className\n )}\n {...props}\n >\n {variant === 'loading' && (\n <span\n aria-hidden=\"true\"\n className=\"size-6 animate-spin rounded-full border-2 border-[var(--ui-glyph-on-surface-primary)] border-t-transparent\"\n />\n )}\n {variant === 'empty' && <InboxIcon size={24} className=\"text-[var(--ui-glyph-on-status-info)]\" />}\n {variant === 'error' && <CircleWarningIcon size={24} className=\"text-[var(--ui-glyph-on-status-warning)]\" />}\n {children}\n {variant === 'error' && action}\n </div>\n )\n);\nInputSelectStatus.displayName = 'InputSelectStatus';\n\nexport {\n InputSelect,\n InputSelectField,\n InputSelectLabel,\n InputSelectTrigger,\n InputSelectValue,\n InputSelectContent,\n InputSelectSearch,\n InputSelectGroup,\n InputSelectSection,\n InputSelectSectionLabel,\n InputSelectItem,\n InputSelectExpander,\n InputSelectDescription,\n InputSelectError,\n InputSelectStatus,\n useInputSelectFilter,\n};\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"input-select.js","names":[],"sources":["../../../../src/components/ui/input-select/input-select.tsx"],"sourcesContent":["import * as React from 'react';\nimport { Select as SelectPrimitive } from '@base-ui/react/select';\nimport {\n CheckSmallIcon,\n ChevronDownIcon,\n ChevronRightIcon,\n CircleWarningIcon,\n InboxIcon,\n MagnifierIcon,\n} from '@acronis-platform/icons-react/stroke-mono';\n\nimport { cn } from '@/lib/utils';\nimport { usePortalContainer } from '@/lib/portal-container';\n\n// The next-gen select, themed by the dedicated `--ui-input-select-*` tier (global /\n// normal / error / dropdown). It composes Base UI `Select` and adds the field\n// furniture (label, required, description, error) and the dropdown machinery\n// (in-dropdown search, sections/groups, single + multiple items, loading/empty/error\n// status). The trigger box wires each state to its own token — idle / hover / open\n// (`data-popup-open`) + focus ring / disabled — and switches to the error border +\n// `--ui-focus-error` ring when `aria-invalid` is set. Selection mode (single vs\n// multiple) flows from the `multiple` prop on the root via `InputSelectModeContext`:\n// single items toggle the row background and show a trailing check; multiple items\n// keep the row background and show a leading checkbox.\n\nconst InputSelectModeContext = React.createContext(false);\n\ninterface InputSelectFilterContextValue {\n /** Current in-dropdown search query. */\n query: string;\n /** Update the search query. */\n setQuery: (query: string) => void;\n}\n\nconst InputSelectFilterContext =\n React.createContext<InputSelectFilterContextValue | null>(null);\n\n/**\n * Read the live in-dropdown search query (and its setter) from the nearest\n * `InputSelect`. Flat item lists filter themselves; use this for hierarchical\n * (tree) dropdowns that need to compute their own visibility.\n */\nfunction useInputSelectFilter(): InputSelectFilterContextValue {\n const context = React.useContext(InputSelectFilterContext);\n if (!context) {\n throw new Error('useInputSelectFilter must be used within <InputSelect>.');\n }\n return context;\n}\n\nfunction InputSelect<Value, Multiple extends boolean | undefined = false>(\n props: SelectPrimitive.Root.Props<Value, Multiple>\n) {\n const { onOpenChange } = props;\n const [query, setQuery] = React.useState('');\n const filter = React.useMemo(() => ({ query, setQuery }), [query]);\n\n // Reset the query when the popup closes so it reopens unfiltered, via two paths.\n // 1. `onOpenChange` — the only path in uncontrolled mode, where Base UI owns the\n // open state and reports every real transition. A consumer that calls\n // `eventDetails.cancel()` keeps the popup open (Base UI skips its own state\n // update too), so the query must survive that.\n // 2. The `open` prop transitioning true -> false — needed in controlled mode,\n // where a consumer can flip its own state directly (e.g. an external toggle\n // button whose click handler runs after it cancelled Base UI's outside-press\n // close) without `onOpenChange` ever firing for that transition. A cancelled\n // close leaves `open` at `true`, so this path preserves the query too.\n const handleOpenChange = React.useCallback<\n NonNullable<SelectPrimitive.Root.Props<Value, Multiple>['onOpenChange']>\n >(\n (open, eventDetails) => {\n onOpenChange?.(open, eventDetails);\n if (!open && !eventDetails.isCanceled) {\n setQuery('');\n }\n },\n [onOpenChange]\n );\n\n const controlledOpen = props.open;\n const previousOpenRef = React.useRef(controlledOpen);\n React.useEffect(() => {\n if (previousOpenRef.current && controlledOpen === false) {\n setQuery('');\n }\n previousOpenRef.current = controlledOpen;\n }, [controlledOpen]);\n\n return (\n <InputSelectModeContext.Provider value={Boolean(props.multiple)}>\n <InputSelectFilterContext.Provider value={filter}>\n <SelectPrimitive.Root {...props} onOpenChange={handleOpenChange} />\n </InputSelectFilterContext.Provider>\n </InputSelectModeContext.Provider>\n );\n}\nInputSelect.displayName = 'InputSelect';\n\nconst InputSelectGroup = SelectPrimitive.Group;\n\n/** Vertical field stack: label, trigger, description/error. */\nconst InputSelectField = React.forwardRef<\n HTMLDivElement,\n React.ComponentPropsWithoutRef<'div'>\n>(({ className, ...props }, ref) => (\n <div\n ref={ref}\n className={cn(\n 'flex min-w-[var(--ui-input-select-global-container-width-min)] flex-col gap-[var(--ui-input-select-global-container-gap)]',\n className\n )}\n {...props}\n />\n));\nInputSelectField.displayName = 'InputSelectField';\n\nconst InputSelectLabel = React.forwardRef<\n React.ElementRef<typeof SelectPrimitive.Label>,\n React.ComponentPropsWithoutRef<typeof SelectPrimitive.Label> & {\n /** Appends a required `*` after the label text. */\n required?: boolean;\n }\n>(({ className, children, required, ...props }, ref) => (\n <SelectPrimitive.Label\n ref={ref}\n className={cn(\n 'flex gap-[var(--ui-input-select-global-container-label-gap)] text-sm leading-4 text-[var(--ui-input-select-global-label-color-idle)] data-[disabled]:text-[var(--ui-input-select-global-label-color-disabled)]',\n className\n )}\n {...props}\n >\n {children}\n {required && (\n <span\n aria-hidden=\"true\"\n className=\"text-[var(--ui-input-select-global-required-color)]\"\n >\n *\n </span>\n )}\n </SelectPrimitive.Label>\n));\nInputSelectLabel.displayName = 'InputSelectLabel';\n\nconst InputSelectTrigger = React.forwardRef<\n React.ElementRef<typeof SelectPrimitive.Trigger>,\n React.ComponentPropsWithoutRef<typeof SelectPrimitive.Trigger>\n>(({ className, children, ...props }, ref) => (\n <SelectPrimitive.Trigger\n ref={ref}\n className={cn(\n 'group flex h-[var(--ui-input-select-global-box-height)] w-full min-w-0 items-center gap-[var(--ui-input-select-global-box-gap)] rounded-[var(--ui-input-select-global-box-border-radius)] border bg-[var(--ui-input-select-global-box-color-idle)] border-[var(--ui-input-select-normal-box-border-color-idle)] px-[var(--ui-input-select-global-box-padding-x)] text-sm leading-6 text-[var(--ui-input-select-global-value-color-idle)] outline-none transition-colors',\n 'not-data-[disabled]:hover:bg-[var(--ui-input-select-global-box-color-hover)] not-data-[disabled]:hover:border-[var(--ui-input-select-normal-box-border-color-hover)]',\n 'focus-visible:border-[var(--ui-input-select-normal-box-border-color-hover)] focus-visible:ring-[3px] focus-visible:ring-[var(--ui-focus-primary)]',\n 'data-[popup-open]:border-[var(--ui-input-select-normal-box-border-color-hover)] data-[popup-open]:ring-[3px] data-[popup-open]:ring-[var(--ui-focus-primary)]',\n 'data-[disabled]:cursor-not-allowed data-[disabled]:border-[var(--ui-input-select-normal-box-border-color-disabled)] data-[disabled]:bg-[var(--ui-input-select-global-box-color-disabled)] data-[disabled]:text-[var(--ui-input-select-global-value-color-disabled)]',\n // Error treatment (driven by `aria-invalid`).\n 'aria-invalid:border-[var(--ui-input-select-error-box-border-color-idle)] not-data-[disabled]:aria-invalid:hover:border-[var(--ui-input-select-error-box-border-color-hover)] aria-invalid:focus-visible:border-[var(--ui-input-select-error-box-border-color-hover)] aria-invalid:focus-visible:ring-[var(--ui-focus-error)] aria-invalid:data-[popup-open]:border-[var(--ui-input-select-error-box-border-color-hover)] aria-invalid:data-[popup-open]:ring-[var(--ui-focus-error)]',\n className\n )}\n {...props}\n >\n {children}\n <SelectPrimitive.Icon className=\"flex size-[var(--ui-input-select-global-icon-box-size)] shrink-0 items-center justify-center text-[var(--ui-input-select-normal-icon-expand-color-idle)] group-data-[disabled]:text-[var(--ui-input-select-normal-icon-expand-color-disabled)]\">\n <ChevronDownIcon\n size={16}\n className=\"transition-transform group-data-[popup-open]:rotate-180\"\n />\n </SelectPrimitive.Icon>\n </SelectPrimitive.Trigger>\n));\nInputSelectTrigger.displayName = 'InputSelectTrigger';\n\nconst InputSelectValue = React.forwardRef<\n React.ElementRef<typeof SelectPrimitive.Value>,\n React.ComponentPropsWithoutRef<typeof SelectPrimitive.Value>\n>(({ className, ...props }, ref) => (\n <SelectPrimitive.Value\n ref={ref}\n className={cn(\n 'min-w-0 flex-1 truncate text-start text-[var(--ui-input-select-global-value-color-idle)] data-[placeholder]:text-[var(--ui-input-select-global-placeholder-color-idle)]',\n 'group-data-[disabled]:!text-[var(--ui-input-select-global-value-color-disabled)] group-data-[disabled]:data-[placeholder]:!text-[var(--ui-input-select-global-placeholder-color-disabled)]',\n className\n )}\n {...props}\n />\n));\nInputSelectValue.displayName = 'InputSelectValue';\n\nconst InputSelectContent = React.forwardRef<\n React.ElementRef<typeof SelectPrimitive.Popup>,\n React.ComponentPropsWithoutRef<typeof SelectPrimitive.Popup> & {\n sideOffset?: number;\n align?: SelectPrimitive.Positioner.Props['align'];\n side?: SelectPrimitive.Positioner.Props['side'];\n /**\n * Offset in px along the alignment axis (perpendicular to `side`). Defaults\n * to Base UI's own `0` when omitted — pass a value to nudge the dropdown\n * along the trigger's edge without changing its `align`.\n */\n alignOffset?: SelectPrimitive.Positioner.Props['alignOffset'];\n /**\n * Collision-avoidance strategy. Defaults to Base UI's own flip/shift\n * behavior, which may move the dropdown off the requested `side`/`align`\n * when it doesn't fit. Pass `{ side: 'none', fallbackAxisSide: 'none' }`\n * alongside an explicit `side`/`align` to lock the popup to that placement\n * with no auto-flip fallback (e.g. \"always to the right, no matter what\":\n * `side=\"right\" sideOffset={20} collisionAvoidance={{ side: 'none',\n * fallbackAxisSide: 'none' }}`).\n */\n collisionAvoidance?: SelectPrimitive.Positioner.Props['collisionAvoidance'];\n /**\n * Element (or ref/getter) the popup positions itself against, overriding\n * the default of anchoring to `InputSelectTrigger`. Use when the visible\n * trigger isn't the element Base UI tracks internally — e.g. an external\n * button drives a hidden trigger, and the popup should align with the\n * button instead of the hidden trigger's layout position.\n */\n anchor?: SelectPrimitive.Positioner.Props['anchor'];\n /**\n * Container to portal the dropdown into. Defaults to the nearest\n * `PortalContainerProvider`, or `document.body` when there is none; pass an\n * element to scope the portal explicitly (e.g. a shadow root, so the popup\n * inherits styles defined there).\n */\n portalContainer?: SelectPrimitive.Portal.Props['container'];\n /**\n * Render the dropdown chrome like `PopoverContent` (`--ui-popover-container-*`\n * tokens, no shadow, fade/zoom/slide enter-exit animation) instead of the\n * default `--ui-input-select-dropdown-container-*` tokens + static `shadow-md`.\n * See `components/ui/popover/popover.tsx`.\n */\n isPopoverStyled?: boolean;\n }\n>(\n (\n {\n className,\n children,\n sideOffset = 4,\n align = 'start',\n side = 'bottom',\n alignOffset,\n collisionAvoidance,\n anchor,\n portalContainer,\n isPopoverStyled = false,\n ...props\n },\n ref\n ) => {\n const ctxContainer = usePortalContainer();\n const resolvedContainer = portalContainer ?? ctxContainer;\n\n return (\n <SelectPrimitive.Portal container={resolvedContainer}>\n <SelectPrimitive.Positioner\n sideOffset={sideOffset}\n align={align}\n side={side}\n alignOffset={alignOffset}\n collisionAvoidance={collisionAvoidance}\n anchor={anchor}\n alignItemWithTrigger={false}\n className=\"z-50 outline-none\"\n >\n <SelectPrimitive.Popup\n ref={ref}\n className={cn(\n 'max-h-[var(--available-height)] min-w-[var(--anchor-width)] overflow-y-auto py-[var(--ui-input-select-dropdown-container-padding-y)] text-sm outline-none',\n // Keep the border/radius/background token references and the animation\n // classes below in sync with PopoverContent's container in popover.tsx —\n // but deliberately NOT its sizing (`min-w`/`max-w`) or `text-foreground`:\n // the dropdown keeps its own `--anchor-width`/`--available-height` sizing\n // and default text color whether or not `isPopoverStyled` is set.\n isPopoverStyled\n ? [\n 'rounded-[var(--ui-popover-container-border-radius)] border-[length:var(--ui-popover-container-border-width)] border-solid border-[var(--ui-popover-container-border-color)] bg-[var(--ui-popover-container-color)]',\n 'duration-200 data-[open]:animate-in data-[closed]:animate-out data-[open]:fade-in-0 data-[closed]:fade-out-0 data-[open]:zoom-in-95 data-[closed]:zoom-out-95',\n 'data-[side=bottom]:slide-in-from-top-2 data-[side=top]:slide-in-from-bottom-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2',\n ]\n : 'rounded-[var(--ui-input-select-dropdown-container-border-radius)] border border-[var(--ui-input-select-dropdown-container-border-color)] bg-[var(--ui-input-select-dropdown-container-color)] shadow-md',\n className\n )}\n {...props}\n >\n {children}\n </SelectPrimitive.Popup>\n </SelectPrimitive.Positioner>\n </SelectPrimitive.Portal>\n );\n }\n);\nInputSelectContent.displayName = 'InputSelectContent';\n\n/**\n * In-dropdown search row (magnifier + input). By default it drives the\n * `InputSelect` filter context — flat `InputSelectItem`s filter themselves, and\n * tree dropdowns read the query via `useInputSelectFilter`. Pass `value`/`onChange`\n * to control the query externally.\n */\nconst InputSelectSearch = React.forwardRef<\n HTMLInputElement,\n React.ComponentPropsWithoutRef<'input'>\n>(({ className, value, onChange, onKeyDown, ...props }, ref) => {\n const filter = React.useContext(InputSelectFilterContext);\n const setQuery = filter?.setQuery;\n const controlled = value !== undefined;\n\n // When the query is controlled externally, the consumer's `value` is the\n // source of truth for what's displayed, so keep the internal filter context\n // (what flat items match against) synced to it. A prop-driven value change —\n // a \"clear\" button resetting to '', a debounced/transformed value — doesn't\n // fire `onChange`, so driving the filter off raw DOM events alone would leave\n // `filter.query` stale and hide every item against a query the box no longer\n // shows. `setQuery` is a stable state setter, so this runs only when `value`\n // changes.\n React.useEffect(() => {\n if (controlled) {\n setQuery?.(String(value ?? ''));\n }\n }, [controlled, value, setQuery]);\n\n return (\n <div className=\"flex items-center gap-[var(--ui-input-select-dropdown-dropdown-search-gap)] px-[var(--ui-input-select-dropdown-dropdown-search-padding-x)] py-[var(--ui-input-select-dropdown-dropdown-search-padding-y)]\">\n <MagnifierIcon\n size={16}\n className=\"shrink-0 text-[var(--ui-glyph-on-surface-primary)]\"\n />\n <input\n ref={ref}\n type=\"search\"\n value={value ?? filter?.query ?? ''}\n onChange={(event) => {\n onChange?.(event);\n // Uncontrolled: the input's value *is* the filter query, so write it\n // straight through. Controlled: the effect above syncs the filter to\n // the consumer's `value` once it re-renders, avoiding a flash of raw\n // typed text when the consumer debounces or transforms the value.\n if (!controlled) {\n filter?.setQuery(event.currentTarget.value);\n }\n }}\n // Base UI Select's typeahead would consume printable keys before they\n // reach this input, so stop those from bubbling — but let navigation and\n // selection keys (Arrow*/Home/End/Enter/Escape, all multi-char `key`\n // names) through so the user can move from the search box into the\n // filtered list and pick a result with the keyboard.\n onKeyDown={(event) => {\n onKeyDown?.(event);\n if (event.key.length === 1) {\n event.stopPropagation();\n }\n }}\n className={cn(\n 'min-w-0 flex-1 border-0 bg-transparent p-0 text-sm leading-6 text-[var(--ui-input-select-dropdown-dropdown-search-label-color-value)] outline-none placeholder:text-[var(--ui-input-select-dropdown-dropdown-search-label-color-placeholder)] [&::-webkit-search-cancel-button]:appearance-none',\n className\n )}\n {...props}\n />\n </div>\n );\n});\nInputSelectSearch.displayName = 'InputSelectSearch';\n\n/** A section (group) of items with an optional header. Divided by a top border. */\nconst InputSelectSection = React.forwardRef<\n React.ElementRef<typeof SelectPrimitive.Group>,\n React.ComponentPropsWithoutRef<typeof SelectPrimitive.Group>\n>(({ className, ...props }, ref) => (\n <SelectPrimitive.Group\n ref={ref}\n className={cn(\n 'flex flex-col border-t border-[var(--ui-input-select-dropdown-section-container-border-color)] py-[var(--ui-input-select-dropdown-section-container-padding-y)] first:border-t-0',\n className\n )}\n {...props}\n />\n));\nInputSelectSection.displayName = 'InputSelectSection';\n\nconst InputSelectSectionLabel = React.forwardRef<\n React.ElementRef<typeof SelectPrimitive.GroupLabel>,\n React.ComponentPropsWithoutRef<typeof SelectPrimitive.GroupLabel>\n>(({ className, ...props }, ref) => (\n <SelectPrimitive.GroupLabel\n ref={ref}\n className={cn(\n 'px-[var(--ui-input-select-dropdown-section-container-header-padding-x)] py-[var(--ui-input-select-dropdown-section-container-header-padding-y)] text-sm font-semibold leading-6 text-[var(--ui-input-select-dropdown-section-label-group-color)]',\n className\n )}\n {...props}\n />\n));\nInputSelectSectionLabel.displayName = 'InputSelectSectionLabel';\n\n/**\n * Width (px) of the leading nesting spacer for a 1-based tree `indent` level, per\n * the Figma \"InputSelectDropdownTenants\" spec: level 1 reserves 16 px (enough for a\n * single chevron) and each deeper level adds 24 px — 16 / 40 / 64 for levels 1–3.\n * The tenant icon therefore starts at the same x-position whether or not the row is\n * expandable, because the chevron lives right-aligned inside this reserved space.\n */\nconst NESTING_BASE = 16;\nconst NESTING_STEP = 24;\nfunction nestingWidth(indent: number): number {\n return NESTING_BASE + (indent - 1) * NESTING_STEP;\n}\n\nexport interface InputSelectItemProps\n extends React.ComponentPropsWithoutRef<typeof SelectPrimitive.Item> {\n /** Optional leading icon rendered before the label text. Colored by `--ui-input-select-dropdown-item-global-icon-tenant`. */\n icon?: React.ReactNode;\n /** 1-based nesting level (0 / omitted = no indent). Levels 1–3 reserve 16 / 40 / 64 px. */\n indent?: number;\n /**\n * Text used to match the in-dropdown search query. Defaults to the string\n * `children`. When a query is active and this text doesn't match, the row hides\n * itself — unless `hidden` is passed explicitly (tree dropdowns compute their own\n * visibility). Rows stay mounted while hidden to keep Base UI's selection index\n * stable.\n */\n textValue?: string;\n}\n\nconst InputSelectItem = React.forwardRef<\n React.ElementRef<typeof SelectPrimitive.Item>,\n InputSelectItemProps\n>(({ className, children, icon, indent, textValue, hidden, ...props }, ref) => {\n const multiple = React.useContext(InputSelectModeContext);\n const filter = React.useContext(InputSelectFilterContext);\n const query = filter?.query.trim().toLowerCase() ?? '';\n const label = textValue ?? (typeof children === 'string' ? children : undefined);\n const autoHidden =\n query.length > 0 && label !== undefined && !label.toLowerCase().includes(query);\n return (\n <SelectPrimitive.Item\n ref={ref}\n hidden={hidden ?? autoHidden}\n className={cn(\n 'group/item relative flex cursor-default items-center gap-[var(--ui-input-select-dropdown-item-global-container-gap)] px-[var(--ui-input-select-dropdown-item-global-container-padding-x)] py-[var(--ui-input-select-dropdown-item-global-container-padding-y)] leading-6 text-[var(--ui-input-select-dropdown-item-global-label-color)] outline-none select-none',\n 'bg-[var(--ui-input-select-dropdown-item-unselected-container-color-idle)] data-[highlighted]:bg-[var(--ui-input-select-dropdown-item-unselected-container-color-hover)]',\n // Single-select rows tint when selected; multiple-select rows keep the\n // unselected background (the leading checkbox carries the state).\n !multiple &&\n 'data-[selected]:bg-[var(--ui-input-select-dropdown-item-selected-container-color-idle)] data-[selected]:data-[highlighted]:bg-[var(--ui-input-select-dropdown-item-selected-container-color-hover)]',\n 'data-[disabled]:pointer-events-none data-[disabled]:bg-[var(--ui-input-select-dropdown-item-unselected-container-color-disabled)]',\n className\n )}\n {...props}\n >\n {multiple && (\n <span\n aria-hidden=\"true\"\n className=\"flex size-[var(--ui-checkbox-global-box-size)] shrink-0 items-center justify-center rounded-[var(--ui-checkbox-global-box-border-radius)] border-[length:var(--ui-checkbox-global-box-border-width)] border-[var(--ui-checkbox-unchecked-box-border-color-idle)] bg-[var(--ui-checkbox-unchecked-box-color-idle)] text-transparent group-data-[selected]/item:border-[var(--ui-checkbox-checked-box-border-color-idle)] group-data-[selected]/item:bg-[var(--ui-checkbox-checked-box-color-idle)] group-data-[selected]/item:text-[var(--ui-checkbox-checked-icon-color-idle)]\"\n >\n <CheckSmallIcon size={16} />\n </span>\n )}\n {typeof indent === 'number' && indent > 0 && (\n <span\n aria-hidden=\"true\"\n className=\"size-4 shrink-0\"\n style={{ minWidth: nestingWidth(indent) }}\n />\n )}\n {icon && (\n <span className=\"flex shrink-0 items-center text-[var(--ui-input-select-dropdown-item-global-icon-tenant)]\">\n {icon}\n </span>\n )}\n <SelectPrimitive.ItemText className=\"min-w-0 flex-1 truncate\">\n {children}\n </SelectPrimitive.ItemText>\n {!multiple && (\n <SelectPrimitive.ItemIndicator className=\"flex shrink-0 items-center text-[var(--ui-input-select-dropdown-item-global-icon-checked)]\">\n <CheckSmallIcon size={16} />\n </SelectPrimitive.ItemIndicator>\n )}\n </SelectPrimitive.Item>\n );\n});\nInputSelectItem.displayName = 'InputSelectItem';\n\nexport interface InputSelectExpanderProps\n extends React.ComponentPropsWithoutRef<'button'> {\n /** Whether the group is currently expanded. */\n expanded: boolean;\n /** Called when the user clicks the row to toggle expand/collapse. */\n onToggle: () => void;\n /** Optional leading icon rendered after the chevron. */\n icon?: React.ReactNode;\n /** 1-based nesting level (0 / omitted = level 1). Levels 1–3 reserve 16 / 40 / 64 px; the chevron sits right-aligned inside. */\n indent?: number;\n}\n\n/**\n * A non-selectable row that acts as an expand/collapse toggle for a tree group.\n * Visually identical to `InputSelectItem` but is **not** a `SelectPrimitive.Item`,\n * so clicking it won't set the select value.\n *\n * When collapsing a group, keep its child `InputSelectItem`s mounted and toggle\n * their `hidden` prop rather than unmounting them: Base UI's Select tracks the\n * selection by list index, so removing the selected row from the DOM makes a\n * sibling inherit its index and render a phantom check. `hidden` rows keep the\n * indices stable and are skipped by keyboard navigation.\n */\nconst InputSelectExpander = React.forwardRef<\n HTMLButtonElement,\n InputSelectExpanderProps\n>(({ className, children, expanded, onToggle, icon, indent, ...props }, ref) => (\n <button\n ref={ref}\n type=\"button\"\n onClick={onToggle}\n aria-expanded={expanded}\n className={cn(\n 'group/item relative flex w-full cursor-default items-center gap-[var(--ui-input-select-dropdown-item-global-container-gap)] px-[var(--ui-input-select-dropdown-item-global-container-padding-x)] py-[var(--ui-input-select-dropdown-item-global-container-padding-y)] text-start leading-6 text-[var(--ui-input-select-dropdown-item-global-label-color)] outline-none select-none',\n 'bg-[var(--ui-input-select-dropdown-item-unselected-container-color-idle)] hover:bg-[var(--ui-input-select-dropdown-item-unselected-container-color-hover)]',\n className\n )}\n {...props}\n >\n <span\n aria-hidden=\"true\"\n className=\"flex shrink-0 items-center justify-end text-[var(--ui-input-select-dropdown-item-global-icon-collapse)]\"\n style={{\n minWidth:\n typeof indent === 'number' && indent > 0 ? nestingWidth(indent) : NESTING_BASE,\n }}\n >\n {expanded ? <ChevronDownIcon size={16} /> : <ChevronRightIcon size={16} />}\n </span>\n {icon && (\n <span className=\"flex shrink-0 items-center text-[var(--ui-input-select-dropdown-item-global-icon-tenant)]\">\n {icon}\n </span>\n )}\n <span className=\"min-w-0 flex-1 truncate\">{children}</span>\n </button>\n));\nInputSelectExpander.displayName = 'InputSelectExpander';\n\nconst InputSelectDescription = React.forwardRef<\n HTMLParagraphElement,\n React.ComponentPropsWithoutRef<'p'>\n>(({ className, ...props }, ref) => (\n <p\n ref={ref}\n className={cn(\n 'text-xs leading-4 text-[var(--ui-input-select-normal-description-color-idle)]',\n className\n )}\n {...props}\n />\n));\nInputSelectDescription.displayName = 'InputSelectDescription';\n\nconst InputSelectError = React.forwardRef<\n HTMLParagraphElement,\n React.ComponentPropsWithoutRef<'p'>\n>(({ className, ...props }, ref) => (\n <p\n ref={ref}\n className={cn(\n 'text-xs leading-4 text-[var(--ui-input-select-error-error-msg-color)]',\n className\n )}\n {...props}\n />\n));\nInputSelectError.displayName = 'InputSelectError';\n\nexport interface InputSelectStatusProps\n extends React.ComponentPropsWithoutRef<'div'> {\n /** Which status to show. Drives the leading icon. */\n variant: 'loading' | 'empty' | 'error';\n /** Optional trailing action (e.g. a \"Try again\" button) — shown for `error`. */\n action?: React.ReactNode;\n}\n\n/** Loading / empty / error status row shown instead of items inside the dropdown. */\nconst InputSelectStatus = React.forwardRef<HTMLDivElement, InputSelectStatusProps>(\n ({ className, variant, children, action, ...props }, ref) => (\n <div\n ref={ref}\n className={cn(\n 'flex min-h-[var(--ui-input-select-dropdown-container-status-width-min)] flex-col items-center justify-center gap-[var(--ui-input-select-dropdown-container-status-gap)] border-t border-[var(--ui-input-select-dropdown-section-container-border-color)] px-[var(--ui-input-select-dropdown-container-status-padding-x)] py-[var(--ui-input-select-dropdown-container-status-padding-y)] text-center text-sm leading-6 text-[var(--ui-input-select-dropdown-item-global-label-color)]',\n className\n )}\n {...props}\n >\n {variant === 'loading' && (\n <span\n aria-hidden=\"true\"\n className=\"size-6 animate-spin rounded-full border-2 border-[var(--ui-glyph-on-surface-primary)] border-t-transparent\"\n />\n )}\n {variant === 'empty' && <InboxIcon size={24} className=\"text-[var(--ui-glyph-on-status-info)]\" />}\n {variant === 'error' && <CircleWarningIcon size={24} className=\"text-[var(--ui-glyph-on-status-warning)]\" />}\n {children}\n {variant === 'error' && action}\n </div>\n )\n);\nInputSelectStatus.displayName = 'InputSelectStatus';\n\nexport {\n InputSelect,\n InputSelectField,\n InputSelectLabel,\n InputSelectTrigger,\n InputSelectValue,\n InputSelectContent,\n InputSelectSearch,\n InputSelectGroup,\n InputSelectSection,\n InputSelectSectionLabel,\n InputSelectItem,\n InputSelectExpander,\n InputSelectDescription,\n InputSelectError,\n InputSelectStatus,\n useInputSelectFilter,\n};\n"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"number-field.js","names":[],"sources":["../../../../src/components/ui/number-field/number-field.tsx"],"sourcesContent":["'use client';\n\nimport * as React from 'react';\nimport { NumberField as NumberFieldPrimitive } from '@base-ui/react/number-field';\nimport { MinusIcon, PlusIcon } from '@acronis-platform/icons-react/stroke-mono';\n\nimport { cn } from '@/lib/utils';\n\n// Ported from `@acronis-platform`'s `number-field`, on Base UI's NumberField\n// (Root / Group / Decrement / Input / Increment). No `--ui-number-field-*` tier —\n// the box reuses the `--ui-input-text-*` tier (already imported) so it matches\n// InputBox / InputText; the steppers use the muted/primary surface + text tokens.\n\nconst NumberField = NumberFieldPrimitive.Root;\n\n// The bordered box wrapping the steppers + input. Mirrors the InputBox field box\n// (height / radius / border / bg / hover / focus-within ring / disabled / invalid).\nconst NumberFieldGroup = React.forwardRef<\n React.ElementRef<typeof NumberFieldPrimitive.Group>,\n React.ComponentPropsWithoutRef<typeof NumberFieldPrimitive.Group>\n>(({ className, ...props }, ref) => (\n <NumberFieldPrimitive.Group\n ref={ref}\n className={cn(\n 'flex h-[var(--ui-input-text-global-box-height)] min-w-0 items-stretch overflow-hidden rounded-[var(--ui-input-text-global-box-border-radius)] border bg-[var(--ui-input-text-global-box-color-idle)] border-[var(--ui-input-text-normal-box-border-color-idle)] transition-colors',\n 'not-has-disabled:hover:border-[var(--ui-input-text-normal-box-border-color-hover)]',\n 'has-[input:focus-visible]:border-[var(--ui-input-text-normal-box-border-color-hover)] has-[input:focus-visible]:ring-[3px] has-[input:focus-visible]:ring-[var(--ui-focus-primary)]',\n 'has-disabled:cursor-not-allowed has-disabled:border-[var(--ui-input-text-normal-box-border-color-disabled)] has-disabled:bg-[var(--ui-input-text-global-box-color-disabled)]',\n 'has-[input[aria-invalid=true]]:border-[var(--ui-input-text-error-msg-box-border-color-idle)] has-[input[aria-invalid=true]:focus-visible]:ring-[var(--ui-focus-error)]',\n className\n )}\n {...props}\n />\n));\nNumberFieldGroup.displayName = 'NumberFieldGroup';\n\nconst NumberFieldInput = React.forwardRef<\n React.ElementRef<typeof NumberFieldPrimitive.Input>,\n React.ComponentPropsWithoutRef<typeof NumberFieldPrimitive.Input>\n>(({ className, ...props }, ref) => (\n <NumberFieldPrimitive.Input\n ref={ref}\n className={cn(\n 'min-w-0 flex-1 bg-transparent px-[var(--ui-input-text-global-box-padding-x)] text-center text-sm leading-6 text-[var(--ui-input-text-global-value-color-idle)] outline-none placeholder:text-[var(--ui-input-text-global-placeholder-color-idle)] disabled:cursor-not-allowed disabled:text-[var(--ui-input-text-global-value-color-disabled)]',\n className\n )}\n {...props}\n />\n));\nNumberFieldInput.displayName = 'NumberFieldInput';\n\nconst stepperClassName =\n 'flex w-9 shrink-0 cursor-pointer items-center justify-center text-[var(--ui-text-on-surface-secondary)] transition-colors not-disabled:hover:bg-[var(--ui-background-surface-hover)] not-disabled:hover:text-[var(--ui-text-on-surface-primary)] disabled:cursor-not-allowed disabled:text-[var(--ui-text-on-surface-disabled)]';\n\nconst NumberFieldDecrement = React.forwardRef<\n React.ElementRef<typeof NumberFieldPrimitive.Decrement>,\n React.ComponentPropsWithoutRef<typeof NumberFieldPrimitive.Decrement>\n>(({ className, children, ...props }, ref) => (\n <NumberFieldPrimitive.Decrement\n ref={ref}\n className={cn(stepperClassName, className)}\n {...props}\n >\n {children ?? <MinusIcon size={16} />}\n </NumberFieldPrimitive.Decrement>\n));\nNumberFieldDecrement.displayName = 'NumberFieldDecrement';\n\nconst NumberFieldIncrement = React.forwardRef<\n React.ElementRef<typeof NumberFieldPrimitive.Increment>,\n React.ComponentPropsWithoutRef<typeof NumberFieldPrimitive.Increment>\n>(({ className, children, ...props }, ref) => (\n <NumberFieldPrimitive.Increment\n ref={ref}\n className={cn(stepperClassName, className)}\n {...props}\n >\n {children ?? <PlusIcon size={16} />}\n </NumberFieldPrimitive.Increment>\n));\nNumberFieldIncrement.displayName = 'NumberFieldIncrement';\n\nexport {\n NumberField,\n NumberFieldGroup,\n NumberFieldInput,\n NumberFieldDecrement,\n NumberFieldIncrement,\n};\n"],"mappings":";;;;;;;AAaA,IAAM,IAAc,EAAqB,MAInC,IAAmB,EAAM,YAG5B,EAAE,cAAW,GAAG,KAAS,MAC1B,kBAAC,EAAqB,OAAtB;CACO;CACL,WAAW,EACT,qRACA,sFACA,uLACA,gLACA,0KACA,CACF;CACA,GAAI;AACL,CAAA,CACF;AACD,EAAiB,cAAc;AAE/B,IAAM,IAAmB,EAAM,YAG5B,EAAE,cAAW,GAAG,KAAS,MAC1B,kBAAC,EAAqB,OAAtB;CACO;CACL,WAAW,EACT,kVACA,CACF;CACA,GAAI;AACL,CAAA,CACF;AACD,EAAiB,cAAc;AAE/B,IAAM,IACJ,mUAEI,IAAuB,EAAM,YAGhC,EAAE,cAAW,aAAU,GAAG,KAAS,MACpC,kBAAC,EAAqB,WAAtB;CACO;CACL,WAAW,EAAG,GAAkB,CAAS;CACzC,GAAI;
|
|
1
|
+
{"version":3,"file":"number-field.js","names":[],"sources":["../../../../src/components/ui/number-field/number-field.tsx"],"sourcesContent":["'use client';\n\nimport * as React from 'react';\nimport { NumberField as NumberFieldPrimitive } from '@base-ui/react/number-field';\nimport { MinusIcon, PlusIcon } from '@acronis-platform/icons-react/stroke-mono';\n\nimport { cn } from '@/lib/utils';\n\n// Ported from `@acronis-platform`'s `number-field`, on Base UI's NumberField\n// (Root / Group / Decrement / Input / Increment). No `--ui-number-field-*` tier —\n// the box reuses the `--ui-input-text-*` tier (already imported) so it matches\n// InputBox / InputText; the steppers use the muted/primary surface + text tokens.\n\nconst NumberField = NumberFieldPrimitive.Root;\n\n// The bordered box wrapping the steppers + input. Mirrors the InputBox field box\n// (height / radius / border / bg / hover / focus-within ring / disabled / invalid).\nconst NumberFieldGroup = React.forwardRef<\n React.ElementRef<typeof NumberFieldPrimitive.Group>,\n React.ComponentPropsWithoutRef<typeof NumberFieldPrimitive.Group>\n>(({ className, ...props }, ref) => (\n <NumberFieldPrimitive.Group\n ref={ref}\n className={cn(\n 'flex h-[var(--ui-input-text-global-box-height)] min-w-0 items-stretch overflow-hidden rounded-[var(--ui-input-text-global-box-border-radius)] border bg-[var(--ui-input-text-global-box-color-idle)] border-[var(--ui-input-text-normal-box-border-color-idle)] transition-colors',\n 'not-has-disabled:hover:border-[var(--ui-input-text-normal-box-border-color-hover)]',\n 'has-[input:focus-visible]:border-[var(--ui-input-text-normal-box-border-color-hover)] has-[input:focus-visible]:ring-[3px] has-[input:focus-visible]:ring-[var(--ui-focus-primary)]',\n 'has-disabled:cursor-not-allowed has-disabled:border-[var(--ui-input-text-normal-box-border-color-disabled)] has-disabled:bg-[var(--ui-input-text-global-box-color-disabled)]',\n 'has-[input[aria-invalid=true]]:border-[var(--ui-input-text-error-msg-box-border-color-idle)] has-[input[aria-invalid=true]:focus-visible]:ring-[var(--ui-focus-error)]',\n className\n )}\n {...props}\n />\n));\nNumberFieldGroup.displayName = 'NumberFieldGroup';\n\nconst NumberFieldInput = React.forwardRef<\n React.ElementRef<typeof NumberFieldPrimitive.Input>,\n React.ComponentPropsWithoutRef<typeof NumberFieldPrimitive.Input>\n>(({ className, ...props }, ref) => (\n <NumberFieldPrimitive.Input\n ref={ref}\n className={cn(\n 'min-w-0 flex-1 bg-transparent px-[var(--ui-input-text-global-box-padding-x)] text-center text-sm leading-6 text-[var(--ui-input-text-global-value-color-idle)] outline-none placeholder:text-[var(--ui-input-text-global-placeholder-color-idle)] disabled:cursor-not-allowed disabled:text-[var(--ui-input-text-global-value-color-disabled)]',\n className\n )}\n {...props}\n />\n));\nNumberFieldInput.displayName = 'NumberFieldInput';\n\nconst stepperClassName =\n 'flex w-9 shrink-0 cursor-pointer items-center justify-center text-[var(--ui-text-on-surface-secondary)] transition-colors not-disabled:hover:bg-[var(--ui-background-surface-hover)] not-disabled:hover:text-[var(--ui-text-on-surface-primary)] disabled:cursor-not-allowed disabled:text-[var(--ui-text-on-surface-disabled)]';\n\nconst NumberFieldDecrement = React.forwardRef<\n React.ElementRef<typeof NumberFieldPrimitive.Decrement>,\n React.ComponentPropsWithoutRef<typeof NumberFieldPrimitive.Decrement>\n>(({ className, children, ...props }, ref) => (\n <NumberFieldPrimitive.Decrement\n ref={ref}\n className={cn(stepperClassName, className)}\n {...props}\n >\n {/* Full-size glyph swapped for a small variant in Checkbox/Combobox/InputSelect/DropdownMenu's selection-indicator role; this is a decrement affordance, not a selection indicator, so it stays until design rules on whether the inset glyph applies here too. */}\n {children ?? <MinusIcon size={16} />}\n </NumberFieldPrimitive.Decrement>\n));\nNumberFieldDecrement.displayName = 'NumberFieldDecrement';\n\nconst NumberFieldIncrement = React.forwardRef<\n React.ElementRef<typeof NumberFieldPrimitive.Increment>,\n React.ComponentPropsWithoutRef<typeof NumberFieldPrimitive.Increment>\n>(({ className, children, ...props }, ref) => (\n <NumberFieldPrimitive.Increment\n ref={ref}\n className={cn(stepperClassName, className)}\n {...props}\n >\n {children ?? <PlusIcon size={16} />}\n </NumberFieldPrimitive.Increment>\n));\nNumberFieldIncrement.displayName = 'NumberFieldIncrement';\n\nexport {\n NumberField,\n NumberFieldGroup,\n NumberFieldInput,\n NumberFieldDecrement,\n NumberFieldIncrement,\n};\n"],"mappings":";;;;;;;AAaA,IAAM,IAAc,EAAqB,MAInC,IAAmB,EAAM,YAG5B,EAAE,cAAW,GAAG,KAAS,MAC1B,kBAAC,EAAqB,OAAtB;CACO;CACL,WAAW,EACT,qRACA,sFACA,uLACA,gLACA,0KACA,CACF;CACA,GAAI;AACL,CAAA,CACF;AACD,EAAiB,cAAc;AAE/B,IAAM,IAAmB,EAAM,YAG5B,EAAE,cAAW,GAAG,KAAS,MAC1B,kBAAC,EAAqB,OAAtB;CACO;CACL,WAAW,EACT,kVACA,CACF;CACA,GAAI;AACL,CAAA,CACF;AACD,EAAiB,cAAc;AAE/B,IAAM,IACJ,mUAEI,IAAuB,EAAM,YAGhC,EAAE,cAAW,aAAU,GAAG,KAAS,MACpC,kBAAC,EAAqB,WAAtB;CACO;CACL,WAAW,EAAG,GAAkB,CAAS;CACzC,GAAI;CAGH,UAAA,KAAY,kBAAC,GAAD,EAAW,MAAM,GAAK,CAAA;AACL,CAAA,CACjC;AACD,EAAqB,cAAc;AAEnC,IAAM,IAAuB,EAAM,YAGhC,EAAE,cAAW,aAAU,GAAG,KAAS,MACpC,kBAAC,EAAqB,WAAtB;CACO;CACL,WAAW,EAAG,GAAkB,CAAS;CACzC,GAAI;CAEH,UAAA,KAAY,kBAAC,GAAD,EAAU,MAAM,GAAK,CAAA;AACJ,CAAA,CACjC;AACD,EAAqB,cAAc"}
|
|
@@ -57,13 +57,18 @@ var v = s.forwardRef(({ className: t, expanded: n, defaultExpanded: r = !0, onEx
|
|
|
57
57
|
});
|
|
58
58
|
});
|
|
59
59
|
v.displayName = "SidebarPrimary";
|
|
60
|
-
var y = s.forwardRef(({ className: t, logo: n, collapsedLogo: r,
|
|
61
|
-
let { expanded:
|
|
60
|
+
var y = s.forwardRef(({ className: t, logo: n, collapsedLogo: r, logoHeight: i, collapsedLogoHeight: a, style: o, children: s, ...c }, u) => {
|
|
61
|
+
let { expanded: d } = h(), f = n != null || r != null ? d ? n ?? r : r ?? n : s;
|
|
62
62
|
return /* @__PURE__ */ l("div", {
|
|
63
|
-
ref:
|
|
63
|
+
ref: u,
|
|
64
64
|
className: e("flex items-center shrink-0 text-[var(--ui-sidebar-primary-global-logo-color)] transition-[padding]", "px-[var(--ui-sidebar-primary-collapsed-container-header-padding-x)] py-[var(--ui-sidebar-primary-collapsed-container-header-padding-y)]", "h-[max(calc(var(--ui-sidebar-primary-collapsed-container-header-padding-y)*2+var(--ui-sidebar-primary-collapsed-logo-height)),calc(var(--ui-sidebar-primary-expanded-container-header-padding-y)*2+var(--ui-sidebar-primary-expanded-logo-height)))]", "[&_:where(img,svg)]:h-[var(--ui-sidebar-primary-collapsed-logo-height)] [&_:where(img,svg)]:w-auto [&_:where(img,svg)]:transition-[height]", "group-data-[state=expanded]/sidebar:px-[var(--ui-sidebar-primary-expanded-container-header-padding-x)] group-data-[state=expanded]/sidebar:py-[var(--ui-sidebar-primary-expanded-container-header-padding-y)]", "group-data-[state=expanded]/sidebar:[&_:where(img,svg)]:h-[var(--ui-sidebar-primary-expanded-logo-height)]", t),
|
|
65
|
-
|
|
66
|
-
|
|
65
|
+
style: {
|
|
66
|
+
...i != null && { "--ui-sidebar-primary-expanded-logo-height": `${i}px` },
|
|
67
|
+
...a != null && { "--ui-sidebar-primary-collapsed-logo-height": `${a}px` },
|
|
68
|
+
...o
|
|
69
|
+
},
|
|
70
|
+
...c,
|
|
71
|
+
children: f
|
|
67
72
|
});
|
|
68
73
|
});
|
|
69
74
|
y.displayName = "SidebarPrimaryHeader";
|