{"version":3,"file":"data-view.types.cjs","sources":["../../../components/data-view/data-view.types.tsx"],"sourcesContent":["import type {\n  ColumnDef,\n  Row,\n  RowSelectionState,\n  Table,\n  Updater,\n  VisibilityState\n} from '@tanstack/table-core';\nimport type {\n  DataTableFilterOperatorTypes,\n  FilterOperatorTypes,\n  FilterSelectOption,\n  FilterTypes,\n  FilterValueType\n} from '~/types/filters';\nimport type { BaseSelectProps } from '../select/select-root';\n\nexport type DataViewMode = 'client' | 'server';\n\nexport const SortOrders = {\n  ASC: 'asc',\n  DESC: 'desc'\n} as const;\n\ntype SortOrdersKeys = keyof typeof SortOrders;\nexport type SortOrdersValues = (typeof SortOrders)[SortOrdersKeys];\n\nexport interface DataViewSort {\n  name: string;\n  order: SortOrdersValues;\n}\n\nexport interface DataViewFilterValues {\n  value: any;\n  boolValue?: boolean;\n  stringValue?: string;\n  numberValue?: number;\n}\n\nexport interface InternalFilter extends DataViewFilterValues {\n  _type?: FilterTypes;\n  _dataType?: FilterValueType;\n  name: string;\n  operator: FilterOperatorTypes;\n}\n\nexport interface DataViewFilter extends DataViewFilterValues {\n  name: string;\n  operator: DataTableFilterOperatorTypes;\n}\n\nexport interface InternalQuery {\n  filters?: InternalFilter[];\n  sort?: DataViewSort[];\n  group_by?: string[];\n  offset?: number;\n  limit?: number;\n  search?: string;\n}\n\nexport interface DataViewQuery extends Omit<InternalQuery, 'filters'> {\n  filters?: DataViewFilter[];\n}\n\n/**\n * Renderer-agnostic field metadata. One entry per logical column of the data\n * model. Declared once on `<DataView>`; drives filter, sort, group, and\n * visibility behaviour across every renderer. Cell/header rendering belongs on\n * each renderer's own column spec, not here.\n */\nexport interface DataViewField<TData = any> {\n  accessorKey: string;\n  /** Human-readable label shown in filter chips, Display controls, and the default Table header. */\n  label: string;\n  icon?: React.ReactNode;\n\n  // filter capability\n  filterable?: boolean;\n  filterType?: FilterTypes;\n  dataType?: FilterValueType;\n  filterOptions?: FilterSelectOption[];\n  defaultFilterValue?: unknown;\n  filterProps?: {\n    select?: BaseSelectProps;\n  };\n\n  // ordering / grouping / visibility capability\n  sortable?: boolean;\n  groupable?: boolean;\n  hideable?: boolean;\n  defaultHidden?: boolean;\n\n  // group-header presentation (used by any renderer that groups)\n  showGroupCount?: boolean;\n  groupCountMap?: Record<string, number>;\n  groupLabelsMap?: Record<string, string>;\n  /**\n   * Section order when this field is the active `group_by`, keyed by raw group\n   * value (the same keys `groupLabelsMap` uses) — e.g.\n   * `['High', 'Medium', 'Low']` for a priority field, which text sorting alone\n   * can't produce.\n   *\n   * Values absent from the list follow in first-seen data order, and rows with\n   * no value always land in the last section. A listed value with no rows\n   * produces no section. Honoured by every renderer that groups.\n   */\n  groupOrder?: string[];\n}\n\n/**\n * Unified column spec for `DataView.List`. The same shape is used for both\n * `variant=\"table\"` and `variant=\"list\"`. The `header` slot is only rendered\n * when headers are visible (default for `variant=\"table\"`).\n */\nexport interface DataViewListColumn<TData, TValue = unknown> {\n  accessorKey: string;\n  /** TanStack-style cell renderer. */\n  cell?: ColumnDef<TData, TValue>['cell'];\n  /** TanStack-style header renderer. Overrides the field's `label`. */\n  header?: ColumnDef<TData, TValue>['header'];\n  /** CSS grid track width. `1fr`, `auto`, `'200px'`, `'minmax(80px, 1fr)'`, or a number (pixels). Defaults to `1fr`. */\n  width?: string | number;\n  /**\n   * @deprecated Every cell and header cell carries `data-column={accessorKey}`\n   * alongside its `data-slot`. Target this column with\n   * `[data-slot=\"data-view-list-cell\"][data-column=\"...\"]` (and the\n   * `-header-cell` variant) instead.\n   */\n  classNames?: { cell?: string; header?: string };\n  styles?: { cell?: React.CSSProperties; header?: React.CSSProperties };\n}\n\n/**\n * Multi-view configuration entry. `value` must match the `name` prop on a\n * renderer; `label` is shown in the view switcher.\n */\nexport interface ViewSpec {\n  value: string;\n  label: string;\n  /** Optional icon rendered before the view's label in the switcher tab. */\n  leadingIcon?: React.ReactNode;\n}\n\n/**\n * Local resolver for a group_by key. Lets a string key in `group_by` (which\n * stays on the wire untouched for server-mode round-trips) map to a function\n * that returns a bucket id per row.\n */\nexport type GroupByResolver<TData> = (row: TData) => string;\n\nexport interface DataViewProps<TData> {\n  data: TData[];\n  /** Renderer-agnostic field metadata. Drives filter/sort/group/visibility. */\n  fields: DataViewField<TData>[];\n  /** Initial query. Transformed to the internal shape on mount. */\n  query?: DataViewQuery;\n  mode?: DataViewMode;\n  isLoading?: boolean;\n  totalRowCount?: number;\n  loadingRowCount?: number;\n  onTableQueryChange?: (query: DataViewQuery) => void;\n  defaultSort: DataViewSort;\n  onLoadMore?: () => Promise<void> | void;\n  onRowClick?: (row: TData) => void;\n  onColumnVisibilityChange?: (columnVisibility: VisibilityState) => void;\n  /**\n   * Fires with the new selection map whenever rows are selected or deselected\n   * (`row.toggleSelected()`, `table.toggleAllRowsSelected()`, …). Selection\n   * itself lives on the table instance — read it through\n   * `useDataView().table`; this is only for mirroring it outside the tree.\n   * Keys are `getRowId` values (row indices when `getRowId` is omitted).\n   */\n  onRowSelectionChange?: (rowSelection: RowSelectionState) => void;\n  /** Stable unique id per row (React key). */\n  getRowId?: (row: TData, index: number) => string;\n  /** Multi-view configuration. When set, `DataView.DisplayControls` renders a view switcher and renderers gate themselves on the active view via their `name` prop. */\n  views?: ViewSpec[];\n  /** Default active view (uncontrolled). Should match a `views[].value`. */\n  defaultView?: string;\n  /** Active view (controlled). */\n  view?: string;\n  /** Called when the active view changes. */\n  onViewChange?: (view: string) => void;\n  /**\n   * Optional local resolver map for non-accessor `group_by` keys. The wire\n   * format (`group_by: string[]`) stays unchanged; resolvers run in client mode\n   * to compute the bucket id per row when a key matches one in this map.\n   */\n  groupByResolvers?: Record<string, GroupByResolver<TData>>;\n}\n\n/** @deprecated Every key here has an equivalent `[data-slot]` selector — see the List slot table in the DataView docs. Prefer styling by `data-slot` over threading class names through props. */\nexport type DataViewListClassNames = {\n  /** @deprecated Use `[data-slot=\"data-view-list\"]` instead. */\n  root?: string;\n  /** @deprecated Use `[data-slot=\"data-view-list-header\"]` instead. */\n  header?: string;\n  /** @deprecated Use `[data-slot=\"data-view-list-header-cell\"]` instead. */\n  headerCell?: string;\n  /** @deprecated Use `[data-slot=\"data-view-list-row\"]` instead. */\n  row?: string;\n  /** @deprecated Use `[data-slot=\"data-view-list-cell\"]` instead. */\n  cell?: string;\n  /** @deprecated Use `[data-slot=\"data-view-list-group-header\"]` instead. */\n  groupHeader?: string;\n};\n\nexport interface DataViewListProps<TData, TValue = unknown> {\n  /** Multi-view name. When set, the renderer gates itself on the active view. */\n  name?: string;\n  /** Visual variant. `table` renders headers and uses `role=\"table\"`; `list` renders no headers and uses `role=\"list\"`. Default `list`. */\n  variant?: 'table' | 'list';\n  /** Override the header row visibility. Defaults to `variant === 'table'`. */\n  showHeaders?: boolean;\n  /** Override the ARIA role applied to the renderer root. Derived from `variant` by default. */\n  role?: 'table' | 'list';\n  /** Optional view-scoped field override. Full replacement of root `fields` for this view's active session. */\n  fields?: DataViewField<TData>[];\n\n  /** Column render specs (cell/header/width/styles). */\n  columns: DataViewListColumn<TData, TValue>[];\n  /**\n   * Initial row-height estimate (px). Rows are auto-measured after they paint,\n   * so this is only used until the first measurement. Default 40 for\n   * `variant=\"table\"`, 56 for `variant=\"list\"`.\n   */\n  estimatedRowHeight?: number;\n  /** When true, only viewport-visible rows render. Parent must have a fixed height. */\n  virtualized?: boolean;\n  /** Render thin dividers between rows. Defaults to true for `variant=\"table\"`. */\n  showDividers?: boolean;\n  /** Show group section headers when grouping is active. Default true. */\n  showGroupHeaders?: boolean;\n  /** When true, group headers stick under the table header while scrolling. Default false. */\n  stickyGroupHeader?: boolean;\n  /** @deprecated Style rendered parts by `[data-slot]` instead — see `DataViewListClassNames`. */\n  classNames?: DataViewListClassNames;\n}\n\n/** Date inputs accepted by Timeline props and row fields: Date, epoch ms, or a parseable string. */\nexport type TimelineDateInput = Date | number | string;\n\n/** Tick granularity of the Timeline axis. */\nexport type TimelineScale = 'day' | 'week' | 'month' | 'quarter';\n\n/** Full-height marker line with a badge pinned to the axis (milestones, deadlines). */\nexport interface TimelineMarker {\n  date: TimelineDateInput;\n  /** Badge content. Defaults to the marker date formatted as \"17 Jan\". */\n  label?: React.ReactNode;\n  variant?: 'default' | 'accent' | 'danger';\n}\n\n/**\n * Geometry + state handed to `renderCard`. The Timeline owns positioning; the\n * consumer owns the card visual and uses this context to adapt it (e.g. render\n * a compact stub when `collapsed`).\n */\nexport interface TimelineCardContext {\n  /** Pixel width of the time span (0 when `endField` is omitted). */\n  width: number;\n  /**\n   * True when the span is narrower than `minCardWidth`. Always false for\n   * point cards (no `endField`) — they size to their content instead.\n   */\n  collapsed: boolean;\n  /**\n   * Lane (row) index assigned by packing. Relative to the card's own group\n   * section when `group_by` is active — every section's first lane is 0.\n   */\n  laneIndex: number;\n  start: Date;\n  /** Null when `endField` is omitted (point marker). */\n  end: Date | null;\n}\n\n/**\n * Imperative navigation surface exposed through `actionsRef` on\n * `DataView.Timeline` (same pattern as Tour's `actionsRef`). Available for the\n * lifetime of the component; methods no-op (with a dev warning) while the\n * renderer is hidden — inactive view or no data.\n */\nexport interface TimelineActions {\n  /**\n   * Scroll the viewport so `target` lands at `align` (default `'center'`).\n   * Accepts the `defaultScrollTo` vocabulary: a date input, `'today'`,\n   * `'start'`, or `'end'` (domain edges). Dates outside the domain clamp to\n   * the nearest edge; invalid dates no-op with a dev warning. Edge\n   * alignments keep a small inset so the target doesn't sit flush against\n   * the viewport edge (yields at the domain edges).\n   */\n  scrollTo: (\n    target: TimelineDateInput | 'today' | 'start' | 'end',\n    options?: {\n      align?: 'start' | 'center' | 'end';\n      /** Default `'smooth'` — a navigation action should visibly travel. */\n      behavior?: 'auto' | 'smooth';\n    }\n  ) => void;\n  /** The visible time window, or null while the renderer is hidden. */\n  getVisibleRange: () => [Date, Date] | null;\n}\n\n/** @deprecated Every key here has an equivalent `[data-slot]` selector — see the Timeline slot table in the DataView docs. Prefer styling by `data-slot` over threading class names through props. */\nexport type DataViewTimelineClassNames = {\n  /** @deprecated Use `[data-slot=\"data-view-timeline\"]` instead. */\n  root?: string;\n  /** @deprecated Use `[data-slot=\"data-view-timeline-axis\"]` instead. */\n  axis?: string;\n  /** @deprecated Use `[data-slot=\"data-view-timeline-axis-band\"]` instead. */\n  band?: string;\n  /** @deprecated Use `[data-slot=\"data-view-timeline-axis-tick\"]` instead. */\n  tick?: string;\n  /** @deprecated Use `[data-slot=\"data-view-timeline-marker\"]` instead. */\n  marker?: string;\n  /** @deprecated Use `[data-slot=\"data-view-timeline-gridline\"]` instead. */\n  gridline?: string;\n  /** @deprecated Use `[data-slot=\"data-view-timeline-cursor\"]` instead. */\n  cursor?: string;\n  /** @deprecated Use `[data-slot=\"data-view-timeline-canvas\"]` instead. */\n  canvas?: string;\n  /** @deprecated Use `[data-slot=\"data-view-timeline-card\"]` instead. */\n  card?: string;\n  /**\n   * Group section header band (same name/role as `DataViewListClassNames.groupHeader`).\n   * @deprecated Use `[data-slot=\"data-view-timeline-group-header\"]` instead.\n   */\n  groupHeader?: string;\n};\n\nexport interface DataViewTimelineProps<TData> {\n  /** Multi-view name. When set, the renderer gates itself on the active view. */\n  name?: string;\n  /**\n   * Accessible name of the scroll region. The pane is keyboard-focusable\n   * (arrow keys scroll it natively), so screen readers announce this label on\n   * focus. Default 'Timeline'.\n   */\n  'aria-label'?: string;\n  /** Optional view-scoped field override. Full replacement of root `fields` for this view's active session. */\n  fields?: DataViewField<TData>[];\n\n  /** Accessor key on the row yielding the start date. Rows with a missing/invalid value are skipped. */\n  startField: string;\n  /** Accessor key for the end date. Omitted → point markers; present → variable-width span cards. */\n  endField?: string;\n\n  /**\n   * Renders the card interior. The Timeline owns positioning (x from start,\n   * width from span, lane from packing, scroll); the consumer owns the card\n   * visual entirely — chrome, states, truncation, and the collapsed variant.\n   * Compose `<DataView.DisplayAccess>` inside for Display Properties support.\n   *\n   * Keep the reference stable (define outside the component or wrap in\n   * `useCallback`) — cards are memoized against it, and an inline function\n   * defeats the memo so every visible card re-renders on each scroll frame.\n   * The same applies to `onRowClick` on the `DataView` root.\n   */\n  renderCard: (\n    row: Row<TData>,\n    context: TimelineCardContext\n  ) => React.ReactNode;\n\n  /** Tick granularity of the time axis. Default 'day'. */\n  scale?: TimelineScale;\n  /** Pixel width of one `scale` unit — density/zoom override. */\n  unitWidth?: number;\n  /**\n   * Explicit time domain. Defaults to the data extent (plus today when shown)\n   * with padding. Either way, a domain narrower than the container is extended\n   * at the end so the axis and gridlines always fill the visible width.\n   */\n  range?: [TimelineDateInput, TimelineDateInput];\n  /** Vertical \"today\" line + axis badge. `true` (default) uses the current date; a date pins it. */\n  today?: boolean | TimelineDateInput;\n  /** Additional full-height marker lines with axis badges. */\n  markers?: TimelineMarker[];\n  /** Vertical gridlines at every axis tick. Default true. */\n  showGridlines?: boolean;\n  /**\n   * Label every Nth `scale` unit on the axis, counted from the domain start\n   * (e.g. `2` on a day scale labels every other day). Labels never render\n   * closer than the collision floor, so a too-dense value degrades gracefully.\n   * Default: the densest interval whose labels fit.\n   */\n  tickInterval?: number;\n  /**\n   * Draw a gridline every Nth `scale` unit, counted from the domain start.\n   * Independent of `tickInterval` and purely visual — cards, the today line,\n   * and the hover cursor still land on every unit. Default 1.\n   */\n  gridlineInterval?: number;\n  /**\n   * Hover crosshair: a darker line snapped to the sub-interval (tick unit)\n   * under the pointer, with a date badge pinned to the axis. Default true.\n   */\n  showCursorLine?: boolean;\n  /** Initial horizontal scroll target. Default 'today'. */\n  defaultScrollTo?: TimelineDateInput | 'today' | 'start' | 'end';\n  /**\n   * After a filter or search change, scroll the earliest matching card into\n   * view when no match intersects the current viewport — otherwise a filter\n   * whose results are off-screen leaves the user parked on empty canvas. A\n   * query change that keeps at least one card on screen doesn't move the\n   * view. Default true.\n   */\n  scrollToResults?: boolean;\n  /** Fires (rAF-throttled) with the visible time range as the user scrolls or resizes. */\n  onVisibleRangeChange?: (range: [Date, Date]) => void;\n  /** Receives the imperative navigation handle (`scrollTo`, `getVisibleRange`). */\n  actionsRef?: React.RefObject<TimelineActions | null>;\n\n  /**\n   * 'auto' (default) packs non-overlapping cards into shared lanes (greedy\n   * interval scheduling); 'one-per-row' gives every row its own lane, in\n   * row-model (sorted) order; 'one-per-sort-value' gives every distinct value of\n   * the **sorted-by** field its own lane, packing that value's cards by date\n   * within it. All apply per group section when `group_by` is active — cards\n   * never share a lane across sections.\n   *\n   * Under 'one-per-sort-value' the active sort does double duty: it picks the field\n   * lanes are built from (sort by `priority` → a High lane, a Medium lane, a\n   * Low lane) and it orders them, so the Ordering control repositions lanes\n   * live. Lane order is the sort's order, so rank values that don't sort\n   * naturally (High/Medium/Low) with a numeric field and sort on that. Rows\n   * whose value is null, empty, or a non-primitive share one lane, placed last.\n   */\n  lanePacking?: 'auto' | 'one-per-row' | 'one-per-sort-value';\n  /**\n   * Lane height in px. Default 66.\n   *\n   * Unvirtualized this is an estimate, same contract as `DataView.List`: cards\n   * render at their natural content height and are measured after paint, the\n   * estimate only seeding lane layout until real heights arrive, and each lane\n   * sizing to its tallest card.\n   *\n   * With `virtualized` it is exact. A culled card never mounts and so never\n   * measures, so measured lanes would resize under the user as they scroll —\n   * lanes take this value instead, and a card taller than it overflows its\n   * lane rather than growing it. Set it to your card's height.\n   */\n  estimatedRowHeight?: number;\n  /** Vertical gap between lanes in px. Default 16. */\n  laneGap?: number;\n  /** Spans narrower than this (px) flip `context.collapsed` for `renderCard`. Default 60. */\n  minCardWidth?: number;\n  /**\n   * Assumed width (px) of point-marker cards (rows without `endField`) for\n   * lane packing. Point cards size to their content, so the packer can't know\n   * their width — set this to roughly the widest point card to prevent\n   * horizontal overlap within a lane. Default 120.\n   */\n  estimatedPointWidth?: number;\n\n  /**\n   * Render only the cards and gridlines near the visible viewport, culling on\n   * both axes — a frame costs what's on screen rather than what's in the data.\n   * Recommended whenever the domain is long or rows are numerous.\n   *\n   * Lane heights become fixed to `estimatedRowHeight`; see the note there.\n   */\n  virtualized?: boolean;\n\n  /**\n   * Render the group header band above each section when `group_by` is active.\n   * Same contract as `DataViewListProps.showGroupHeaders`: false hides the\n   * bands only — rows stay grouped into their sections. Default true.\n   */\n  showGroupHeaders?: boolean;\n  /** @deprecated Style rendered parts by `[data-slot]` instead — see `DataViewTimelineClassNames`. */\n  classNames?: DataViewTimelineClassNames;\n}\n\nexport type TableQueryUpdateFn = (query: InternalQuery) => InternalQuery;\n\nexport type DataViewContextType<TData> = {\n  table: Table<TData>;\n  /** Effective fields for the active view (= override fields if registered, else root fields). */\n  fields: DataViewField<TData>[];\n  /** Root-declared fields, unchanged by view overrides. */\n  rootFields: DataViewField<TData>[];\n\n  // data\n  data: TData[];\n  isLoading?: boolean;\n  loadMoreData: () => void;\n  mode: DataViewMode;\n  defaultSort: DataViewSort;\n  tableQuery: InternalQuery;\n  totalRowCount?: number;\n  loadingRowCount?: number;\n  onDisplaySettingsReset: () => void;\n  updateTableQuery: (fn: TableQueryUpdateFn) => void;\n  onRowClick?: (row: TData) => void;\n  shouldShowFilters: boolean;\n\n  // visibility (lifted to context per RFC §\"Unified Column Visibility via DisplayAccess\")\n  columnVisibility: VisibilityState;\n  setColumnVisibility: (value: Updater<VisibilityState>) => void;\n\n  // selection — lifted so a selection change invalidates this context value\n  // (the table instance identity is stable, so it can't do that on its own).\n  rowSelection: RowSelectionState;\n  setRowSelection: (value: Updater<RowSelectionState>) => void;\n\n  // multi-view\n  views?: ViewSpec[];\n  activeView?: string;\n  setActiveView: (view: string) => void;\n  /** Called by each renderer on mount to register its `fields` override for its `name`. Returns a cleanup function. */\n  registerFieldsForView: (\n    name: string,\n    fields: DataViewField<TData>[]\n  ) => () => void;\n\n  // global derived state — shared across all renderers and sibling components\n  hasData: boolean;\n  hasActiveQuery: boolean;\n  isZeroState: boolean;\n  isEmptyState: boolean;\n};\n\nexport interface ColumnData {\n  label: string;\n  id: string;\n  isVisible?: boolean;\n}\n\ninterface SubRows<_T> {}\n\nexport interface GroupedData<T> extends SubRows<T> {\n  label: string;\n  group_key: string;\n  subRows: T[];\n  count?: number;\n  showGroupCount?: boolean;\n}\n\nexport const defaultGroupOption = {\n  id: '--',\n  label: 'No grouping'\n};\n"],"names":[],"mappings":";;AAmBa,MAAA,UAAU,GAAG;AACxB,IAAA,GAAG,EAAE,KAAK;AACV,IAAA,IAAI,EAAE,MAAM;EACH;AAogBE,MAAA,kBAAkB,GAAG;AAChC,IAAA,EAAE,EAAE,IAAI;AACR,IAAA,KAAK,EAAE,aAAa;;;;;;"}