@datum-cloud/datum-ui 3.8.0 → 3.10.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.
Files changed (52) hide show
  1. package/dist/autocomplete/index.mjs +1 -1
  2. package/dist/{autocomplete-D0zAcT78.mjs → autocomplete-CrCbO2VS.mjs} +10 -4
  3. package/dist/autosearch/index.mjs +1 -1
  4. package/dist/button-group/index.mjs +1 -1
  5. package/dist/{button-group-C3GKo-0p.mjs → button-group-DJ6X1SSj.mjs} +2 -2
  6. package/dist/{calendar-date-picker-CknZM6a2.mjs → calendar-date-picker-BRKs56gR.mjs} +1 -1
  7. package/dist/components/features/logs/hooks/use-logs-url-state.d.ts +59 -0
  8. package/dist/components/features/logs/index.d.ts +4 -1
  9. package/dist/components/features/logs/utils/facet-counts.d.ts +50 -0
  10. package/dist/components/features/logs/utils/facets.d.ts +2 -0
  11. package/dist/components/features/logs/utils/index.d.ts +4 -0
  12. package/dist/components/features/logs/utils/url-state.d.ts +61 -0
  13. package/dist/data-table/index.mjs +1 -1
  14. package/dist/{data-table-CpBwO8Ea.mjs → data-table-DFUnUydN.mjs} +5 -5
  15. package/dist/date-picker/index.mjs +3 -3
  16. package/dist/date-time-picker/index.mjs +1 -1
  17. package/dist/{date-time-picker-Bc41Ixrs.mjs → date-time-picker-BRMm2QSz.mjs} +1 -1
  18. package/dist/{date-time-range-picker-yy1Acntn.mjs → date-time-range-picker-CqGGJTLS.mjs} +18 -7
  19. package/dist/field-styles-D-FJatHt.mjs +31 -0
  20. package/dist/form/index.mjs +1 -1
  21. package/dist/{form-DTaVgDSV.mjs → form-VdbSqDjL.mjs} +5 -5
  22. package/dist/grouped-table/index.mjs +1 -1
  23. package/dist/{grouped-table-Dl6DclbV.mjs → grouped-table-B4HzLXq6.mjs} +1 -1
  24. package/dist/hooks/index.mjs +1 -1
  25. package/dist/hooks/use-breakpoint.d.ts +7 -2
  26. package/dist/index.mjs +19 -19
  27. package/dist/{layers-DLUbkJtt.mjs → layers-BC1Ny49w.mjs} +1 -1
  28. package/dist/logs/index.mjs +374 -80
  29. package/dist/map/index.mjs +1 -1
  30. package/dist/more-actions/index.mjs +1 -1
  31. package/dist/{more-actions-BlSOVwa8.mjs → more-actions-DXQiV-bN.mjs} +1 -1
  32. package/dist/multi-select/index.mjs +1 -1
  33. package/dist/{multi-select-C2cBrqXl.mjs → multi-select-DwcsJdHt.mjs} +32 -24
  34. package/dist/picker/index.mjs +2 -2
  35. package/dist/{picker-DC3GErYg.mjs → picker-BHPtncpv.mjs} +2 -2
  36. package/dist/responsive-dropdown/index.mjs +1 -1
  37. package/dist/{responsive-dropdown-DsWgpE_i.mjs → responsive-dropdown-B9cDUeHt.mjs} +1 -1
  38. package/dist/responsive-popover/index.mjs +1 -1
  39. package/dist/{responsive-popover-DJYd8lOK.mjs → responsive-popover-B_pUxrZ1.mjs} +1 -1
  40. package/dist/rich-text-editor/index.mjs +1 -1
  41. package/dist/{rich-text-editor-BUz06s-b.mjs → rich-text-editor-CPd_6vdZ.mjs} +1 -1
  42. package/dist/select/index.mjs +1 -1
  43. package/dist/{select-DemYhwnG.mjs → select-B0Xlz-wD.mjs} +3 -2
  44. package/dist/{select-jgK6wyXj.mjs → select-CGsHf70u.mjs} +7 -2
  45. package/dist/task-queue/index.mjs +1 -1
  46. package/dist/{task-queue-dropdown-DuCAAybs.mjs → task-queue-dropdown-BflEFiMi.mjs} +1 -1
  47. package/dist/time-picker/index.mjs +1 -1
  48. package/dist/{time-picker-B_am4eAK.mjs → time-picker-BFwH-Vd3.mjs} +1 -1
  49. package/dist/{to-api-format-DyImCzCn.mjs → to-api-format-BiWOTFha.mjs} +3 -3
  50. package/dist/{use-breakpoint-zY_JYINK.mjs → use-breakpoint-Ce5tS4cU.mjs} +11 -5
  51. package/dist/utils/field-styles.d.ts +21 -0
  52. package/package.json +1 -1
@@ -1 +1 @@
1
- export { t as Autocomplete } from "../autocomplete-D0zAcT78.mjs";
1
+ export { t as Autocomplete } from "../autocomplete-CrCbO2VS.mjs";
@@ -1,6 +1,8 @@
1
1
  import { t as cn } from "./utils-CTIuhCOs.mjs";
2
2
  import { n as OptionList, t as useOptionPicker } from "./use-option-picker-DXY2SNnT.mjs";
3
- import { t as ResponsivePopover } from "./responsive-popover-DJYd8lOK.mjs";
3
+ import { t as ResponsivePopover } from "./responsive-popover-B_pUxrZ1.mjs";
4
+ import { n as fieldPlaceholderClassName, r as fieldTriggerClassName, t as fieldIconClassName } from "./field-styles-D-FJatHt.mjs";
5
+ import { t as Icon } from "./icon-wrapper-CIk2th6R.mjs";
4
6
  import { t as LoaderOverlay } from "./loader-overlay-DP0pvHuG.mjs";
5
7
  import { ChevronDown } from "lucide-react";
6
8
  import * as React from "react";
@@ -17,7 +19,7 @@ function Trigger({ ref, selectedOption, createdValue, renderValue, placeholder,
17
19
  children: createdValue
18
20
  });
19
21
  else displayContent = /* @__PURE__ */ jsx("span", {
20
- className: "text-muted-foreground",
22
+ className: cn("truncate", fieldPlaceholderClassName),
21
23
  children: placeholder
22
24
  });
23
25
  return /* @__PURE__ */ jsxs("button", {
@@ -27,7 +29,7 @@ function Trigger({ ref, selectedOption, createdValue, renderValue, placeholder,
27
29
  role: "combobox",
28
30
  "aria-expanded": open,
29
31
  disabled: disabled || loading,
30
- className: cn("text-input-foreground placeholder:text-input-placeholder", "border-input-border bg-input-background/50 relative flex h-10 w-full items-center justify-between rounded-lg border px-3 py-2 text-left text-sm transition-all", "focus-visible:border-input-focus-border focus-visible:shadow-(--input-focus-shadow)", "focus-visible:ring-0 focus-visible:ring-offset-0 focus-visible:outline-hidden", "aria-invalid:border-destructive", (disabled || loading) && "cursor-not-allowed opacity-50", className),
32
+ className: cn(fieldTriggerClassName, "relative h-10 justify-between py-2", (disabled || loading) && "cursor-not-allowed opacity-50", className),
31
33
  ...rest,
32
34
  children: [
33
35
  loading && /* @__PURE__ */ jsx(LoaderOverlay, {}),
@@ -35,7 +37,11 @@ function Trigger({ ref, selectedOption, createdValue, renderValue, placeholder,
35
37
  className: "min-w-0 flex-1",
36
38
  children: displayContent
37
39
  }),
38
- /* @__PURE__ */ jsx(ChevronDown, { className: "text-muted-foreground ml-2 size-4 shrink-0" })
40
+ /* @__PURE__ */ jsx(Icon, {
41
+ icon: ChevronDown,
42
+ className: fieldIconClassName,
43
+ "aria-hidden": "true"
44
+ })
39
45
  ]
40
46
  });
41
47
  }
@@ -2,7 +2,7 @@ import { t as cn } from "../utils-CTIuhCOs.mjs";
2
2
  import { t as Button } from "../button-Cn4KagBO.mjs";
3
3
  import { t as Input } from "../input-DsT5qkJn.mjs";
4
4
  import { n as OptionList, t as useOptionPicker } from "../use-option-picker-DXY2SNnT.mjs";
5
- import { t as ResponsivePopover } from "../responsive-popover-DJYd8lOK.mjs";
5
+ import { t as ResponsivePopover } from "../responsive-popover-B_pUxrZ1.mjs";
6
6
  import { t as Tooltip } from "../tooltip-OIySjJWW.mjs";
7
7
  import { AlertCircle, Loader2, X } from "lucide-react";
8
8
  import * as React from "react";
@@ -1 +1 @@
1
- export { t as ButtonGroup, n as ButtonGroupSeparator, r as ButtonGroupText, i as buttonGroupVariants } from "../button-group-C3GKo-0p.mjs";
1
+ export { t as ButtonGroup, n as ButtonGroupSeparator, r as ButtonGroupText, i as buttonGroupVariants } from "../button-group-DJ6X1SSj.mjs";
@@ -4,7 +4,7 @@ import { cva } from "class-variance-authority";
4
4
  import { jsx } from "react/jsx-runtime";
5
5
  import { Slot } from "@radix-ui/react-slot";
6
6
  // ../shadcn/ui/button-group.tsx
7
- const buttonGroupVariants = cva("flex w-fit items-stretch has-[>[data-slot=button-group]]:gap-2 [&>*]:focus-visible:relative [&>*]:focus-visible:z-10 has-[select[aria-hidden=true]:last-child]:[&>[data-slot=select-trigger]:last-of-type]:rounded-r-md [&>[data-slot=select-trigger]:not([class*='w-'])]:w-fit [&>input]:flex-1", {
7
+ const buttonGroupVariants = cva("flex w-fit items-stretch has-[>[data-slot=button-group]]:gap-2 [&>*]:focus-visible:relative [&>*]:focus-visible:z-10 has-[select[aria-hidden=true]:last-child]:[&>[data-slot=select-trigger]:last-of-type]:rounded-r-lg [&>[data-slot=select-trigger]:not([class*='w-'])]:w-fit [&>input]:flex-1", {
8
8
  variants: { orientation: {
9
9
  horizontal: "[&>*:not(:first-child)]:rounded-l-none [&>*:not(:first-child)]:border-l-0 [&>*:not(:last-child)]:rounded-r-none",
10
10
  vertical: "flex-col [&>*:not(:first-child)]:rounded-t-none [&>*:not(:first-child)]:border-t-0 [&>*:not(:last-child)]:rounded-b-none"
@@ -22,7 +22,7 @@ function ButtonGroup({ className, orientation, ...props }) {
22
22
  }
23
23
  function ButtonGroupText({ className, asChild = false, ...props }) {
24
24
  return /* @__PURE__ */ jsx(asChild ? Slot : "div", {
25
- className: cn("bg-muted flex items-center gap-2 rounded-md border px-4 text-sm font-medium shadow-xs [&_svg]:pointer-events-none [&_svg:not([class*='size-'])]:size-4", className),
25
+ className: cn("bg-muted text-muted-foreground border-input-border flex items-center gap-2 rounded-lg border px-3 text-sm font-normal [&_svg]:pointer-events-none [&_svg:not([class*='size-'])]:size-4", className),
26
26
  ...props
27
27
  });
28
28
  }
@@ -1,5 +1,5 @@
1
1
  import { t as useDeprecationWarning } from "./use-deprecation-warning-BS1V4IS5.mjs";
2
- import { a as DateRangePicker } from "./picker-DC3GErYg.mjs";
2
+ import { a as DateRangePicker } from "./picker-BHPtncpv.mjs";
3
3
  import { jsx } from "react/jsx-runtime";
4
4
  // src/components/features/calendar-date-picker/calendar-date-picker.tsx
5
5
  /**
@@ -0,0 +1,59 @@
1
+ import type { LogFilters, LogTimeRange } from '../types';
2
+ import type { LogsUrlState, LogsUrlStateOptions } from '../utils/url-state';
3
+ type SearchParamsUpdate = (prev: URLSearchParams) => URLSearchParams;
4
+ /**
5
+ * Updates the query string. Shaped like React Router's `setSearchParams`, so
6
+ * `useSearchParams()` from `react-router` plugs straight in.
7
+ */
8
+ export type SetLogsSearchParams = (update: SearchParamsUpdate, options?: {
9
+ replace?: boolean;
10
+ }) => void;
11
+ export interface UseLogsUrlStateOptions extends LogsUrlStateOptions {
12
+ /**
13
+ * Current query string, from the app's router. Pass it together with
14
+ * `setSearchParams` whenever the app has a client router that owns the URL
15
+ * (React Router, TanStack Router): writing `window.history` behind its back
16
+ * leaves the router's location stale, and its next navigation can drop these
17
+ * params. Leave both out only for plain pages or Next.js App Router, which
18
+ * follows History API calls itself.
19
+ */
20
+ searchParams?: URLSearchParams;
21
+ setSearchParams?: SetLogsSearchParams;
22
+ /**
23
+ * `replace` (default) rewrites the current history entry, so the back button
24
+ * leaves the page instead of stepping through every filter click. `push`
25
+ * adds an entry per change.
26
+ */
27
+ history?: 'replace' | 'push';
28
+ }
29
+ /** Values and change handlers to spread onto `Logs.Root`. */
30
+ export interface LogsUrlStateProps extends LogsUrlState {
31
+ onTimeRangeChange: (range: LogTimeRange) => void;
32
+ onFiltersChange: (filters: LogFilters) => void;
33
+ onSearchChange: (search: string) => void;
34
+ onLiveChange: (live: boolean) => void;
35
+ onSelectedIdChange: (id: string | null) => void;
36
+ }
37
+ /**
38
+ * Keep `Logs.Root`'s time range, filters, search, live toggle and open row in
39
+ * the address bar, so a refresh or a shared link reopens the same view.
40
+ *
41
+ * ```tsx
42
+ * const logsState = useLogsUrlState()
43
+ * const query = buildLogQL({ matchers: logsState.filters, lineContains: logsState.search })
44
+ * // fetch with query + resolveLogTimeRange(logsState.timeRange)
45
+ *
46
+ * <Logs.Root {...logsState} entries={entries} onRefresh={refetch}>
47
+ * <Logs.Explorer />
48
+ * </Logs.Root>
49
+ * ```
50
+ *
51
+ * With React Router, hand it the router's search params instead:
52
+ *
53
+ * ```tsx
54
+ * const [searchParams, setSearchParams] = useSearchParams()
55
+ * const logsState = useLogsUrlState({ searchParams, setSearchParams })
56
+ * ```
57
+ */
58
+ export declare function useLogsUrlState(options?: UseLogsUrlStateOptions): LogsUrlStateProps;
59
+ export {};
@@ -1,5 +1,8 @@
1
1
  export { resolveLogColumns } from './components/columns';
2
2
  export { useLogs } from './hooks/use-logs';
3
+ export { useLogsUrlState } from './hooks/use-logs-url-state';
4
+ export type { LogsUrlStateProps, SetLogsSearchParams, UseLogsUrlStateOptions } from './hooks/use-logs-url-state';
3
5
  export { Logs } from './logs';
4
6
  export type { BuildLogQLOptions, LogColumn, LogColumnCellContext, LogColumnId, LogColumnSize, LogColumnSkeletonContext, LogColumnSpec, LogEntry, LogFacet, LogFacetOption, LogFilters, LogHistogramBucket, LogsContextValue, LogsRootProps, LogTimeRange, LokiQueryRangeResponse, LokiStream, ParsedHttpLogLine, ParsedLogLine, ParsedTextLogLine, } from './types';
5
- export { buildLogQL, facetsFromEntries, filterEntries, flattenLokiStreams, formatHttpLogLine, histogramFromEntries, httpStatusBadgeType, httpStatusTextClass, lastThirtyMinutes, LOG_TIME_PRESETS, logLineDisplay, logRequestHost, logTimeRangeLabel, logUserAgent, nsToDate, parseLogLine, parseUserAgent, resolveLogTimeRange, searchableLogText, severityBadgeType, splitPathQuery, } from './utils';
7
+ export { buildLogFacetCountQuery, buildLogQL, facetFromLokiCounts, facetsFromEntries, filterEntries, flattenLokiStreams, formatHttpLogLine, histogramFromEntries, httpStatusBadgeType, httpStatusTextClass, lastThirtyMinutes, LOG_TIME_PRESETS, logLineDisplay, logRequestHost, LOGS_URL_KEYS, logTimeRangeLabel, logUserAgent, nsToDate, parseLogLine, parseLogsUrlState, parseUserAgent, resolveLogTimeRange, searchableLogText, severityBadgeType, splitPathQuery, writeLogsUrlState, } from './utils';
8
+ export type { BuildLogFacetCountQueryOptions, LogsUrlState, LogsUrlStateOptions, LokiVectorResponse, LokiVectorSample } from './utils';
@@ -0,0 +1,50 @@
1
+ import type { LogFacet, LogFilters, LogTimeRange } from '../types';
2
+ export interface BuildLogFacetCountQueryOptions {
3
+ /** Label to count values of, e.g. `response_code`. */
4
+ label: string;
5
+ /**
6
+ * Matchers that scope the page, e.g. `{ route_name: ['my-alb'] }`. Leave the
7
+ * user's facet selections and search out: counting against the scope alone
8
+ * keeps every option listed, with its total for the window, no matter what
9
+ * is ticked.
10
+ */
11
+ matchers?: LogFilters;
12
+ /** Window to count over. Its length becomes the range selector. */
13
+ timeRange: LogTimeRange;
14
+ }
15
+ /**
16
+ * LogQL that counts log lines per value of one label across a time range:
17
+ *
18
+ * ```
19
+ * sum by (response_code) (count_over_time({route_name="my-alb"}[1800s]))
20
+ * ```
21
+ *
22
+ * Run it as an instant query (`/loki/api/v1/query`) with `time` set to the
23
+ * range's `to`, then pass the response to `facetFromLokiCounts`. Returns
24
+ * `null` for a label name LogQL can't express. Works for indexed stream labels
25
+ * and for structured metadata, which Loki can also group by.
26
+ */
27
+ export declare function buildLogFacetCountQuery({ label, matchers, timeRange }: BuildLogFacetCountQueryOptions): string | null;
28
+ /** One series of a Loki instant-query (`resultType: 'vector'`) response. */
29
+ export interface LokiVectorSample {
30
+ metric: Record<string, string>;
31
+ value: [timestamp: number | string, value: string];
32
+ }
33
+ export interface LokiVectorResponse {
34
+ status: 'success' | 'error';
35
+ data?: {
36
+ resultType: string;
37
+ result: LokiVectorSample[];
38
+ };
39
+ errorType?: string;
40
+ error?: string;
41
+ }
42
+ /**
43
+ * Turn the response to a `buildLogFacetCountQuery` query into a facet for
44
+ * `Logs.Root`. Series without the label (lines that don't carry it) and zero
45
+ * counts are skipped. Options are ordered the same way as `facetsFromEntries`.
46
+ * Pass `label` to override the display name.
47
+ */
48
+ export declare function facetFromLokiCounts(name: string, response: LokiVectorResponse | null | undefined, options?: {
49
+ label?: string;
50
+ }): LogFacet;
@@ -1,4 +1,6 @@
1
1
  import type { LogEntry, LogFacet, LogFilters } from '../types';
2
+ export declare function facetLabel(name: string): string;
3
+ export declare function compareFacetValues(name: string, a: string, b: string): number;
2
4
  export declare function facetsFromEntries(entries: readonly LogEntry[], names?: readonly string[]): LogFacet[];
3
5
  export declare function filterEntries(entries: readonly LogEntry[], filters: LogFilters, search?: string): LogEntry[];
4
6
  /**
@@ -1,5 +1,7 @@
1
1
  export { buildLogQL } from './build-logql';
2
2
  export { CANONICAL_FACET_NAMES, DEFAULT_LOG_COLUMNS, DEFAULT_LOGQL_MATCHER, FACET_LABELS, SEVERITY_ORDER, } from './constants';
3
+ export { buildLogFacetCountQuery, facetFromLokiCounts } from './facet-counts';
4
+ export type { BuildLogFacetCountQueryOptions, LokiVectorResponse, LokiVectorSample } from './facet-counts';
3
5
  export { facetsFromEntries, filterEntries, searchableLogText } from './facets';
4
6
  export { flattenLokiStreams, nsToDate } from './flatten-loki';
5
7
  export { formatLocalTimestamp, formatLogTimestamp, formatLogTimestampParts, formatRelativeTimestamp, formatUtcTimestamp, } from './format-timestamp';
@@ -8,5 +10,7 @@ export { logRequestHost } from './host';
8
10
  export { formatHttpLogLine, logLineDisplay, parseLogLine, splitPathQuery } from './parse-log-line';
9
11
  export { httpStatusBadgeType, httpStatusTextClass, severityBadgeType } from './severity';
10
12
  export { filtersAreActive, lastThirtyMinutes, LOG_TIME_PRESETS, logTimeRangeLabel, resolveLogTimeRange, } from './time-range';
13
+ export { LOGS_URL_KEYS, logsUrlStateKey, parseLogsUrlState, writeLogsUrlState } from './url-state';
14
+ export type { LogsUrlState, LogsUrlStateOptions } from './url-state';
11
15
  export { logUserAgent, parseUserAgent } from './user-agent';
12
16
  export type { ParsedUserAgent, UserAgentDevice } from './user-agent';
@@ -0,0 +1,61 @@
1
+ import type { LogFilters, LogTimeRange } from '../types';
2
+ /**
3
+ * The parts of `Logs.Root` state that belong in the address bar: everything
4
+ * that decides which logs the host fetches, plus the open row.
5
+ */
6
+ export interface LogsUrlState {
7
+ timeRange: LogTimeRange;
8
+ filters: LogFilters;
9
+ search: string;
10
+ live: boolean;
11
+ selectedId: string | null;
12
+ }
13
+ export interface LogsUrlStateOptions {
14
+ /**
15
+ * Prepended to every key, e.g. `logs.` gives `logs.q`, `logs.range`. Use it
16
+ * when two explorers share a page, or a key clashes with one the app owns.
17
+ */
18
+ prefix?: string;
19
+ /**
20
+ * Range used when the URL has none, and left out of the URL when chosen.
21
+ * Defaults to the last 30 minutes.
22
+ */
23
+ defaultTimeRange?: LogTimeRange;
24
+ }
25
+ /**
26
+ * Query-string keys, before `prefix`. A preset range is written as
27
+ * `range=last-1h`; a hand-picked one as `from` and `to` ISO timestamps. Each
28
+ * selected facet value is its own `filter=<label>:<value>` entry.
29
+ */
30
+ export declare const LOGS_URL_KEYS: {
31
+ readonly search: "q";
32
+ readonly range: "range";
33
+ readonly from: "from";
34
+ readonly to: "to";
35
+ readonly filter: "filter";
36
+ readonly live: "live";
37
+ readonly selected: "log";
38
+ };
39
+ /**
40
+ * Read logs state from a query string. Missing or malformed values fall back
41
+ * to the defaults (`Logs.Root`'s own defaults), so a hand-edited or stale link
42
+ * still opens. A preset range is resolved against `now`.
43
+ */
44
+ export declare function parseLogsUrlState(input: URLSearchParams | string, options?: LogsUrlStateOptions & {
45
+ now?: Date;
46
+ }): LogsUrlState;
47
+ /**
48
+ * Return a copy of `input` with the given parts of logs state written in.
49
+ * Only the parts present in `state` are touched, and params the app owns are
50
+ * kept. Defaults (no search, no filters, not live, the default range) are
51
+ * left out so a fresh explorer has a clean URL.
52
+ */
53
+ export declare function writeLogsUrlState(input: URLSearchParams | string, state: Partial<LogsUrlState>, options?: LogsUrlStateOptions): URLSearchParams;
54
+ /**
55
+ * Just this explorer's params, as a query string in a fixed key order. It
56
+ * parses to the same state as the full query string, and only changes when
57
+ * one of these params does, so it works as a memo key: an unrelated app param
58
+ * changing won't re-resolve a preset range (which would hand the host a new
59
+ * `timeRange` and trigger a refetch).
60
+ */
61
+ export declare function logsUrlStateKey(input: URLSearchParams | string, options?: Pick<LogsUrlStateOptions, 'prefix'>): string;
@@ -1 +1 @@
1
- export { v as DEFAULT_DEBOUNCE_MS, y as DEFAULT_LOADING_ROWS, b as DEFAULT_PAGE_SIZE, x as DEFAULT_PAGE_SIZES, t as DataTable, h as DataTableColumnHeader, m as DataTableRowActions, u as createDataTableStore, g as createSelectionColumn, p as dataTableFeatures, d as resolvePath, f as rowMatchesSearch, n as useDataTableFilters, r as useDataTableInlineContents, i as useDataTableLoading, a as useDataTablePagination, o as useDataTableRows, s as useDataTableSearch, c as useDataTableSelection, l as useDataTableSorting, _ as useNuqsAdapter } from "../data-table-CpBwO8Ea.mjs";
1
+ export { v as DEFAULT_DEBOUNCE_MS, y as DEFAULT_LOADING_ROWS, b as DEFAULT_PAGE_SIZE, x as DEFAULT_PAGE_SIZES, t as DataTable, h as DataTableColumnHeader, m as DataTableRowActions, u as createDataTableStore, g as createSelectionColumn, p as dataTableFeatures, d as resolvePath, f as rowMatchesSearch, n as useDataTableFilters, r as useDataTableInlineContents, i as useDataTableLoading, a as useDataTablePagination, o as useDataTableRows, s as useDataTableSearch, c as useDataTableSelection, l as useDataTableSorting, _ as useNuqsAdapter } from "../data-table-DFUnUydN.mjs";
@@ -1,17 +1,17 @@
1
1
  import { t as Checkbox } from "./checkbox-BAo5sbHk.mjs";
2
2
  import { t as cn } from "./utils-CTIuhCOs.mjs";
3
3
  import { t as Button } from "./button-Cn4KagBO.mjs";
4
- import { t as ResponsiveDropdown } from "./responsive-dropdown-DsWgpE_i.mjs";
4
+ import { t as ResponsiveDropdown } from "./responsive-dropdown-B9cDUeHt.mjs";
5
5
  import { t as ActionRow } from "./action-row-BEzE9x37.mjs";
6
6
  import { Badge } from "./badge/index.mjs";
7
7
  import { Skeleton } from "./skeleton/index.mjs";
8
8
  import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from "./table/index.mjs";
9
- import { i as SelectItem, l as SelectTrigger, n as SelectContent, t as Select, u as SelectValue } from "./select-DemYhwnG.mjs";
9
+ import { i as SelectItem, l as SelectTrigger, n as SelectContent, t as Select, u as SelectValue } from "./select-B0Xlz-wD.mjs";
10
10
  import { t as Input } from "./input-DsT5qkJn.mjs";
11
11
  import { n as useDebouncedSearchInput } from "./use-debounced-search-input-B4u28iLx.mjs";
12
- import { t as MultiSelect } from "./multi-select-C2cBrqXl.mjs";
13
- import { t as CalendarDatePicker } from "./calendar-date-picker-CknZM6a2.mjs";
14
- import { t as Autocomplete } from "./autocomplete-D0zAcT78.mjs";
12
+ import { t as MultiSelect } from "./multi-select-DwcsJdHt.mjs";
13
+ import { t as CalendarDatePicker } from "./calendar-date-picker-BRKs56gR.mjs";
14
+ import { t as Autocomplete } from "./autocomplete-CrCbO2VS.mjs";
15
15
  import { ArrowDown, ArrowUp, ArrowUpDown, ChevronLeft, ChevronRight, MoreHorizontal, Search, X } from "lucide-react";
16
16
  import { createContext, memo, use, useCallback, useContext, useEffect, useId, useMemo, useRef, useState, useSyncExternalStore } from "react";
17
17
  import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
@@ -1,4 +1,4 @@
1
- import { M as getBrowserTimezone, N as getTimezoneOffset, j as formatTimezoneLabel } from "../date-time-range-picker-yy1Acntn.mjs";
2
- import { t as CalendarDatePicker } from "../calendar-date-picker-CknZM6a2.mjs";
3
- import { _ as getShortTimezoneDisplay, a as TimeRangePicker, b as utcToLocalInputString, c as getPresetByKey, d as TimezoneSelector, f as QuickRangesPanel, g as getDefaultTimezoneOptions, h as formatUtcForDisplay, i as formatTimeRangeDisplay, l as getPresetByShortcut, m as createTimezoneOption, n as formatDateForInput, o as DEFAULT_PRESETS, p as CustomRangePanel, r as formatSingleTimeDisplay, s as getDefaultPreset, t as toApiTimeRange, u as getPresetRange, v as localInputStringToUtc, x as zonedDateToUtcString, y as utcStringToZonedDate } from "../to-api-format-DyImCzCn.mjs";
1
+ import { M as getBrowserTimezone, N as getTimezoneOffset, j as formatTimezoneLabel } from "../date-time-range-picker-CqGGJTLS.mjs";
2
+ import { t as CalendarDatePicker } from "../calendar-date-picker-BRKs56gR.mjs";
3
+ import { _ as getShortTimezoneDisplay, a as TimeRangePicker, b as utcToLocalInputString, c as getPresetByKey, d as TimezoneSelector, f as QuickRangesPanel, g as getDefaultTimezoneOptions, h as formatUtcForDisplay, i as formatTimeRangeDisplay, l as getPresetByShortcut, m as createTimezoneOption, n as formatDateForInput, o as DEFAULT_PRESETS, p as CustomRangePanel, r as formatSingleTimeDisplay, s as getDefaultPreset, t as toApiTimeRange, u as getPresetRange, v as localInputStringToUtc, x as zonedDateToUtcString, y as utcStringToZonedDate } from "../to-api-format-BiWOTFha.mjs";
4
4
  export { CustomRangePanel as AbsoluteRangePanel, CustomRangePanel, CalendarDatePicker, DEFAULT_PRESETS, QuickRangesPanel, TimeRangePicker, TimezoneSelector, createTimezoneOption, formatDateForInput, formatSingleTimeDisplay, formatTimeRangeDisplay, formatTimezoneLabel, formatUtcForDisplay, getBrowserTimezone, getDefaultPreset, getDefaultTimezoneOptions, getPresetByKey, getPresetByShortcut, getPresetRange, getShortTimezoneDisplay, getTimezoneOffset, localInputStringToUtc, toApiTimeRange, utcStringToZonedDate, utcToLocalInputString, zonedDateToUtcString };
@@ -1 +1 @@
1
- export { t as DateTimePicker } from "../date-time-picker-Bc41Ixrs.mjs";
1
+ export { t as DateTimePicker } from "../date-time-picker-BRMm2QSz.mjs";
@@ -1,5 +1,5 @@
1
1
  import { t as useDeprecationWarning } from "./use-deprecation-warning-BS1V4IS5.mjs";
2
- import { r as DateTimePicker$1 } from "./picker-DC3GErYg.mjs";
2
+ import { r as DateTimePicker$1 } from "./picker-BHPtncpv.mjs";
3
3
  import { jsx } from "react/jsx-runtime";
4
4
  // src/components/features/date-time-picker/date-time-picker.tsx
5
5
  /**
@@ -1,9 +1,11 @@
1
1
  import { Calendar } from "./calendar/index.mjs";
2
2
  import { t as cn } from "./utils-CTIuhCOs.mjs";
3
- import { t as ResponsivePopover } from "./responsive-popover-DJYd8lOK.mjs";
3
+ import { t as ResponsivePopover } from "./responsive-popover-B_pUxrZ1.mjs";
4
4
  import { t as Button } from "./button-C57mkFkS.mjs";
5
- import { t as useBreakpoint } from "./use-breakpoint-zY_JYINK.mjs";
5
+ import { t as useBreakpoint } from "./use-breakpoint-Ce5tS4cU.mjs";
6
6
  import { n as OptionList, t as useOptionPicker } from "./use-option-picker-DXY2SNnT.mjs";
7
+ import { r as fieldTriggerClassName, t as fieldIconClassName } from "./field-styles-D-FJatHt.mjs";
8
+ import { t as Icon } from "./icon-wrapper-CIk2th6R.mjs";
7
9
  import { t as Button$1 } from "./button-Cn4KagBO.mjs";
8
10
  import { CalendarIcon, Clock, Globe, X } from "lucide-react";
9
11
  import { createContext, useCallback, useContext, useEffect, useMemo, useReducer, useRef, useState } from "react";
@@ -1272,7 +1274,11 @@ function PickerTimezoneIndicator({ className, variant = "full" }) {
1272
1274
  }
1273
1275
  PickerTimezoneIndicator.displayName = "Picker.TimezoneIndicator";
1274
1276
  // src/components/features/picker/components/trigger.tsx
1275
- const DEFAULT_ICON = /* @__PURE__ */ jsx(CalendarIcon, { className: "text-muted-foreground size-4 shrink-0" });
1277
+ const DEFAULT_ICON = /* @__PURE__ */ jsx(Icon, {
1278
+ icon: CalendarIcon,
1279
+ className: fieldIconClassName,
1280
+ "aria-hidden": "true"
1281
+ });
1276
1282
  function PickerTrigger({ placeholder = "Pick a date", clearable = false, disabled = false, children, className, triggerClassName, id, icon, onClick, ...slotProps }) {
1277
1283
  const { state, actions } = usePickerContext();
1278
1284
  const hasValue = state.pendingValue !== null && state.pendingValue !== void 0;
@@ -1290,12 +1296,12 @@ function PickerTrigger({ placeholder = "Pick a date", clearable = false, disable
1290
1296
  if (state.open) actions.close();
1291
1297
  else actions.open();
1292
1298
  },
1293
- className: cn("w-full justify-between gap-2 rounded-lg font-normal", triggerClassName, className),
1299
+ className: cn(fieldTriggerClassName, "h-10 justify-between hover:bg-input-background/50 hover:text-input-foreground", triggerClassName, className),
1294
1300
  ...slotProps,
1295
1301
  children: [/* @__PURE__ */ jsxs("span", {
1296
1302
  className: "flex flex-1 items-center gap-2 truncate",
1297
1303
  children: [renderedIcon, /* @__PURE__ */ jsx("span", {
1298
- className: cn("truncate", !hasValue && "text-muted-foreground"),
1304
+ className: cn("truncate", !hasValue && "text-input-placeholder"),
1299
1305
  children: hasValue ? children ? children(state.pendingValue) : String(state.pendingValue) : placeholder
1300
1306
  })]
1301
1307
  }), clearable && hasValue && /* @__PURE__ */ jsx("button", {
@@ -1305,8 +1311,13 @@ function PickerTrigger({ placeholder = "Pick a date", clearable = false, disable
1305
1311
  e.stopPropagation();
1306
1312
  actions.clear();
1307
1313
  },
1308
- className: "text-muted-foreground hover:text-destructive shrink-0 rounded-sm p-0.5 transition-colors",
1309
- children: /* @__PURE__ */ jsx(X, { className: "size-3.5" })
1314
+ className: "text-muted-foreground hover:text-destructive -m-0.5 shrink-0 rounded-sm p-0.5 transition-colors",
1315
+ children: /* @__PURE__ */ jsx(Icon, {
1316
+ icon: X,
1317
+ size: 14,
1318
+ className: "size-3.5! shrink-0",
1319
+ "aria-hidden": "true"
1320
+ })
1310
1321
  })]
1311
1322
  });
1312
1323
  }
@@ -0,0 +1,31 @@
1
+ // src/utils/field-styles.ts
2
+ /**
3
+ * Shared look for every input-like trigger: Select, Autocomplete, MultiSelect
4
+ * and the date/time pickers. They sit next to each other in toolbars and
5
+ * filter rows, so they must line up with `Input` and with each other:
6
+ *
7
+ * - 12px (`px-3`) inline padding, the same as `Input`
8
+ * - `text-sm`, regular weight for both the value and the placeholder
9
+ * - 8px (`gap-2`) between the leading icon, the value and trailing icons
10
+ * - trailing chevrons are 16px and muted, with no extra margin, so the
11
+ * chevron sits 12px from the right edge on every trigger
12
+ * - clear (X) icons are 14px: lucide's X fills more of its box than the
13
+ * chevron, so at 16px it looks heavier than the chevron beside it
14
+ *
15
+ * Internal: not part of the public `utils` entry.
16
+ */
17
+ /** Box, type and focus styles. Height is left to each component. */
18
+ const fieldTriggerClassName = [
19
+ "flex w-full items-center gap-2 rounded-lg border px-3 text-left text-sm font-normal",
20
+ "border-input-border bg-input-background/50 text-input-foreground shadow-none",
21
+ "transition-[color,background-color,border-color,box-shadow] outline-none",
22
+ "focus-visible:border-input-focus-border focus-visible:shadow-(--input-focus-shadow)",
23
+ "focus-visible:ring-0 focus-visible:ring-offset-0",
24
+ "aria-invalid:border-destructive",
25
+ "disabled:cursor-not-allowed disabled:opacity-50"
26
+ ].join(" ");
27
+ /** Placeholder text inside a trigger. Same colour as `Input`'s placeholder. */
28
+ const fieldPlaceholderClassName = "text-input-placeholder";
29
+ /** Leading icons and the trailing chevron. Clear icons use `size-3.5`. */
30
+ const fieldIconClassName = "text-muted-foreground size-4 shrink-0";
31
+ export { fieldPlaceholderClassName as n, fieldTriggerClassName as r, fieldIconClassName as t };
@@ -1,3 +1,3 @@
1
- import { A as FormCheckbox, C as FormDialog, D as FormCustom, E as FormDatePicker, M as FormAutosearch, N as FormAutocomplete, O as FormCopyBox, S as FormError, T as FormDateTimePicker, _ as FormRadioGroup, a as useField, b as FormFieldArray, c as useWatchAll, d as FormTextarea, f as FormSwitch, g as FormRoot, h as FormSelectItem, i as useFieldContext, j as FormButton, k as FormCombobox, l as FormTransfer, m as FormSelect, n as useFormState, o as FormWhen, p as FormSubmit, r as useFormContext, s as useWatch, t as Form, u as FormTimePicker, v as FormRadioItem, w as FormDescription, x as FormField, y as FormInput } from "../form-DTaVgDSV.mjs";
1
+ import { A as FormCheckbox, C as FormDialog, D as FormCustom, E as FormDatePicker, M as FormAutosearch, N as FormAutocomplete, O as FormCopyBox, S as FormError, T as FormDateTimePicker, _ as FormRadioGroup, a as useField, b as FormFieldArray, c as useWatchAll, d as FormTextarea, f as FormSwitch, g as FormRoot, h as FormSelectItem, i as useFieldContext, j as FormButton, k as FormCombobox, l as FormTransfer, m as FormSelect, n as useFormState, o as FormWhen, p as FormSubmit, r as useFormContext, s as useWatch, t as Form, u as FormTimePicker, v as FormRadioItem, w as FormDescription, x as FormField, y as FormInput } from "../form-VdbSqDjL.mjs";
2
2
  import { n as useAdapter, t as FormAdapterProvider } from "../adapter-context-XT749tyT.mjs";
3
3
  export { Form, FormAdapterProvider, FormAutocomplete, FormAutosearch, FormButton, FormCheckbox, FormCombobox, FormCopyBox, FormCustom, FormDatePicker, FormDateTimePicker, FormDescription, FormDialog, FormError, FormField, FormFieldArray, FormInput, FormRadioGroup, FormRadioItem, FormRoot, FormSelect, FormSelectItem, FormSubmit, FormSwitch, FormTextarea, FormTimePicker, FormTransfer, FormWhen, useAdapter, useField, useFieldContext, useFormContext, useFormState, useWatch, useWatchAll };
@@ -1,5 +1,5 @@
1
1
  import { t as cn } from "./utils-CTIuhCOs.mjs";
2
- import { t as Autocomplete } from "./autocomplete-D0zAcT78.mjs";
2
+ import { t as Autocomplete } from "./autocomplete-CrCbO2VS.mjs";
3
3
  import { Autosearch } from "./autosearch/index.mjs";
4
4
  import { t as Button } from "./button-Cn4KagBO.mjs";
5
5
  import { n as useFormContext$1, t as FormProvider } from "./form-context-BRzt53M5.mjs";
@@ -8,8 +8,8 @@ import { t as Label } from "./label-BR1V3Imy.mjs";
8
8
  import { t as toast } from "./toast-CizxCEcK.mjs";
9
9
  import { t as useCopyToClipboard } from "./use-copy-to-clipboard-CWKWHLxI.mjs";
10
10
  import { t as CopyStateIcon } from "./copy-state-icon-DMvXXsZm.mjs";
11
- import { t as CalendarDatePicker } from "./calendar-date-picker-CknZM6a2.mjs";
12
- import { t as DateTimePicker } from "./date-time-picker-Bc41Ixrs.mjs";
11
+ import { t as CalendarDatePicker } from "./calendar-date-picker-BRKs56gR.mjs";
12
+ import { t as DateTimePicker } from "./date-time-picker-BRMm2QSz.mjs";
13
13
  import { t as Dialog } from "./dialog-C8RXIQYm.mjs";
14
14
  import { t as useControllableState } from "./use-controllable-state-DLeVgbAb.mjs";
15
15
  import { t as Tooltip } from "./tooltip-OIySjJWW.mjs";
@@ -18,10 +18,10 @@ import { n as useAdapter } from "./adapter-context-XT749tyT.mjs";
18
18
  import { t as Input } from "./input-DsT5qkJn.mjs";
19
19
  import { InputWithAddons } from "./input-with-addons/index.mjs";
20
20
  import { n as RadioGroupItem, t as RadioGroup } from "./radio-group-Boxi2hm0.mjs";
21
- import { i as SelectItem, l as SelectTrigger, n as SelectContent, t as Select, u as SelectValue } from "./select-DemYhwnG.mjs";
21
+ import { i as SelectItem, l as SelectTrigger, n as SelectContent, t as Select, u as SelectValue } from "./select-B0Xlz-wD.mjs";
22
22
  import { t as Switch } from "./switch-IduVwiPZ.mjs";
23
23
  import { t as Textarea } from "./textarea-CvhdK6JY.mjs";
24
- import { t as TimePicker } from "./time-picker-B_am4eAK.mjs";
24
+ import { t as TimePicker } from "./time-picker-BFwH-Vd3.mjs";
25
25
  import { t as Transfer } from "./transfer-DGUeAQUL.mjs";
26
26
  import { CircleHelp } from "lucide-react";
27
27
  import * as React from "react";
@@ -1 +1 @@
1
- export { t as GroupedTable } from "../grouped-table-Dl6DclbV.mjs";
1
+ export { t as GroupedTable } from "../grouped-table-B4HzLXq6.mjs";
@@ -2,7 +2,7 @@ import { t as cn } from "./utils-CTIuhCOs.mjs";
2
2
  import { r as CollapsibleTrigger, t as Collapsible } from "./collapsible-B-KP3JZ-.mjs";
3
3
  import { TableBody, TableCell, TableHead, TableHeader, TableRow } from "./table/index.mjs";
4
4
  import { t as Icon } from "./icon-wrapper-CIk2th6R.mjs";
5
- import { f as rowMatchesSearch, g as createSelectionColumn, h as DataTableColumnHeader, m as DataTableRowActions, p as dataTableFeatures } from "./data-table-CpBwO8Ea.mjs";
5
+ import { f as rowMatchesSearch, g as createSelectionColumn, h as DataTableColumnHeader, m as DataTableRowActions, p as dataTableFeatures } from "./data-table-DFUnUydN.mjs";
6
6
  import { n as EASE } from "./motion-DOrRbLmy.mjs";
7
7
  import { Skeleton } from "./skeleton/index.mjs";
8
8
  import { n as useDebouncedSearchInput } from "./use-debounced-search-input-B4u28iLx.mjs";
@@ -1,4 +1,4 @@
1
- import { t as useBreakpoint } from "../use-breakpoint-zY_JYINK.mjs";
1
+ import { t as useBreakpoint } from "../use-breakpoint-Ce5tS4cU.mjs";
2
2
  import { n as useDebouncedSearchInput, t as DEFAULT_SEARCH_DEBOUNCE_MS } from "../use-debounced-search-input-B4u28iLx.mjs";
3
3
  import { t as useCopyToClipboard } from "../use-copy-to-clipboard-CWKWHLxI.mjs";
4
4
  import { t as useDebounce } from "../hooks-WVJbyhCz.mjs";
@@ -3,6 +3,11 @@ export type BreakpointTier = 'mobile' | 'tablet' | 'desktop';
3
3
  * Returns the current viewport breakpoint tier.
4
4
  *
5
5
  * Breakpoints: mobile <768px, tablet 768–1023px, desktop ≥1024px.
6
- * SSR-safe: defaults to 'desktop' on server; client corrects on mount.
6
+ *
7
+ * `initial` is the tier the server rendered with. Pass the viewport the server
8
+ * already knows about (for example a viewport client hint) so the hydration
9
+ * render matches; without one it defaults to 'desktop'. The client measures on
10
+ * mount and tracks resizes after that, so the first render stays deterministic
11
+ * on both sides.
7
12
  */
8
- export declare function useBreakpoint(): BreakpointTier;
13
+ export declare function useBreakpoint(initial?: BreakpointTier): BreakpointTier;