@cryptlex/web-components 6.6.6-alpha08 → 6.6.6-alpha10

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.
@@ -1,2 +1,2 @@
1
- import{jsx as e,Fragment as c}from"react/jsx-runtime";import{Checkbox as u,composeRenderProps as a,CheckboxGroup as m}from"react-aria-components";import{FormField as b,labelVariants as p}from"./field.js";import{useTfFieldContext as h}from"../utilities/form.js";import{classNames as d}from"../utilities/theme.js";import{IcMinus as x,IcCheck as g}from"./icons.js";import"class-variance-authority";import"react";import"../utilities/form-context.js";import"@tanstack/react-form";import"clsx";const j=m;function f({className:r,label:o,description:s,errorMessage:n,...l}){return e("div",{className:"group form-field",children:e(b,{label:o,description:s,errorMessage:n,children:e(u,{className:a(r,t=>d("group/checkbox cursor-pointer focus-ring flex items-center gap-x-2","disabled-muted",p,t)),...l,children:a(e(c,{}),(t,i)=>e(c,{children:e("div",{className:d("flex size-input shrink-0 items-center bg-popover justify-center border border-input text-current ring-offset-background","group-data-[indeterminate]/checkbox:bg-primary group-data-[selected]/checkbox:bg-primary group-data-[indeterminate]/checkbox:text-primary-foreground group-data-[selected]/checkbox:text-primary-foreground","group-data-[disabled]/checkbox:cursor-not-allowed group-data-[disabled]/checkbox:opacity-50","group-data-[invalid]/checkbox:border-destructive group-data-[invalid]/checkbox:group-data-[selected]/checkbox:bg-destructive group-data-[invalid]/checkbox:group-data-[selected]/checkbox:text-destructive-foreground","focus:outline-none focus-visible:outline-none"),children:i.isIndeterminate?e(x,{className:"size-icon"}):i.isSelected?e(g,{className:"size-icon"}):null})}))})})})}function B({...r}){const o=h({disabled:r.isDisabled});return e(f,{isSelected:o.state.value,isDisabled:o.form.state.isSubmitting||r.isDisabled,onChange:()=>o.handleChange(!o.state.value),onBlur:o.handleBlur,...r})}export{f as Checkbox,j as CheckboxGroup,B as TfCheckbox};
1
+ import{jsx as e,Fragment as c}from"react/jsx-runtime";import{Checkbox as u,composeRenderProps as a,CheckboxGroup as m}from"react-aria-components";import{FormField as b,labelVariants as p}from"./field.js";import{useFieldContext as h}from"../utilities/form-context.js";import{classNames as d}from"../utilities/theme.js";import{IcMinus as x,IcCheck as g}from"./icons.js";import"class-variance-authority";import"@tanstack/react-form";import"react";import"clsx";const S=m;function f({className:r,label:o,description:s,errorMessage:n,...l}){return e("div",{className:"group form-field",children:e(b,{label:o,description:s,errorMessage:n,children:e(u,{className:a(r,t=>d("group/checkbox cursor-pointer focus-ring flex items-center gap-x-2","disabled-muted",p,t)),...l,children:a(e(c,{}),(t,i)=>e(c,{children:e("div",{className:d("flex size-input shrink-0 items-center bg-popover justify-center border border-input text-current ring-offset-background","group-data-[indeterminate]/checkbox:bg-primary group-data-[selected]/checkbox:bg-primary group-data-[indeterminate]/checkbox:text-primary-foreground group-data-[selected]/checkbox:text-primary-foreground","group-data-[disabled]/checkbox:cursor-not-allowed group-data-[disabled]/checkbox:opacity-50","group-data-[invalid]/checkbox:border-destructive group-data-[invalid]/checkbox:group-data-[selected]/checkbox:bg-destructive group-data-[invalid]/checkbox:group-data-[selected]/checkbox:text-destructive-foreground","focus:outline-none focus-visible:outline-none"),children:i.isIndeterminate?e(x,{className:"size-icon"}):i.isSelected?e(g,{className:"size-icon"}):null})}))})})})}function j({...r}){const o=h({disabled:r.isDisabled});return e(f,{isSelected:o.state.value,isDisabled:o.form.state.isSubmitting||r.isDisabled,onChange:()=>o.handleChange(!o.state.value),onBlur:o.handleBlur,...r})}export{f as Checkbox,S as CheckboxGroup,j as TfCheckbox};
2
2
  //# sourceMappingURL=checkbox.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"checkbox.js","sources":["../../lib/components/checkbox.tsx"],"sourcesContent":["import {\n Checkbox as AriaCheckbox,\n CheckboxGroup as AriaCheckboxGroup,\n composeRenderProps,\n type CheckboxProps as AriaCheckboxProps,\n} from 'react-aria-components';\n\nimport { FormField, labelVariants, type FormFieldProps } from '../components/field';\nimport { useTfFieldContext } from '../utilities/form';\nimport { classNames } from '../utilities/theme';\nimport { IcCheck, IcMinus } from './icons';\n\nexport const CheckboxGroup = AriaCheckboxGroup;\ntype CheckboxProps = AriaCheckboxProps & FormFieldProps;\nexport function Checkbox({ className, label, description, errorMessage, ...props }: Omit<CheckboxProps, 'children'>) {\n return (\n <div className=\"group form-field\">\n <FormField label={label} description={description} errorMessage={errorMessage}>\n <AriaCheckbox\n className={composeRenderProps(className, className =>\n classNames(\n 'group/checkbox cursor-pointer focus-ring flex items-center gap-x-2',\n /* Disabled */\n 'disabled-muted',\n labelVariants,\n className\n )\n )}\n {...props}\n >\n {composeRenderProps(<></>, (_, renderProps) => (\n <>\n <div\n className={classNames(\n 'flex size-input shrink-0 items-center bg-popover justify-center border border-input text-current ring-offset-background',\n /* Selected */\n 'group-data-[indeterminate]/checkbox:bg-primary group-data-[selected]/checkbox:bg-primary group-data-[indeterminate]/checkbox:text-primary-foreground group-data-[selected]/checkbox:text-primary-foreground',\n /* Disabled */\n 'group-data-[disabled]/checkbox:cursor-not-allowed group-data-[disabled]/checkbox:opacity-50',\n /* Invalid */\n 'group-data-[invalid]/checkbox:border-destructive group-data-[invalid]/checkbox:group-data-[selected]/checkbox:bg-destructive group-data-[invalid]/checkbox:group-data-[selected]/checkbox:text-destructive-foreground',\n /* Resets */\n 'focus:outline-none focus-visible:outline-none'\n )}\n >\n {renderProps.isIndeterminate ? (\n <IcMinus className=\"size-icon\" />\n ) : renderProps.isSelected ? (\n <IcCheck className=\"size-icon\" />\n ) : null}\n </div>\n </>\n ))}\n </AriaCheckbox>\n </FormField>\n </div>\n );\n}\n\nexport type TfCheckboxProps = Omit<React.ComponentProps<typeof Checkbox>, 'onChange' | 'onBlur' | 'isChecked'>;\nexport function TfCheckbox({ ...props }: TfCheckboxProps) {\n const field = useTfFieldContext<boolean>({ disabled: props.isDisabled });\n return (\n <Checkbox\n isSelected={field.state.value}\n isDisabled={field.form.state.isSubmitting || props.isDisabled}\n onChange={() => field.handleChange(!field.state.value)}\n onBlur={field.handleBlur}\n {...props}\n />\n );\n}\n"],"names":["CheckboxGroup","AriaCheckboxGroup","Checkbox","className","label","description","errorMessage","props","jsx","FormField","AriaCheckbox","composeRenderProps","classNames","labelVariants","Fragment","_","renderProps","IcMinus","IcCheck","TfCheckbox","field","useTfFieldContext"],"mappings":"weAYO,MAAMA,EAAgBC,EAEtB,SAASC,EAAS,CAAE,UAAAC,EAAW,MAAAC,EAAO,YAAAC,EAAa,aAAAC,EAAc,GAAGC,GAA0C,CACjH,OACIC,EAAC,OAAI,UAAU,mBACX,WAACC,EAAA,CAAU,MAAAL,EAAc,YAAAC,EAA0B,aAAAC,EAC/C,SAAAE,EAACE,EAAA,CACG,UAAWC,EAAmBR,EAAWA,GACrCS,EACI,qEAEA,iBACAC,EACAV,CAAA,CACJ,EAEH,GAAGI,EAEH,WAAmBC,EAAAM,EAAA,CAAA,CAAE,EAAK,CAACC,EAAGC,IAC3BR,EAAAM,EAAA,CACI,SAAAN,EAAC,MAAA,CACG,UAAWI,EACP,0HAEA,+MAEA,8FAEA,wNAEA,+CAAA,EAGH,SAAAI,EAAY,gBACTR,EAACS,EAAA,CAAQ,UAAU,WAAA,CAAY,EAC/BD,EAAY,WACZR,EAACU,EAAA,CAAQ,UAAU,YAAY,EAC/B,IAAA,CAAA,EAEZ,CACH,CAAA,CAAA,EAET,CAAA,CACJ,CAER,CAGO,SAASC,EAAW,CAAE,GAAGZ,GAA0B,CACtD,MAAMa,EAAQC,EAA2B,CAAE,SAAUd,EAAM,WAAY,EACvE,OACIC,EAACN,EAAA,CACG,WAAYkB,EAAM,MAAM,MACxB,WAAYA,EAAM,KAAK,MAAM,cAAgBb,EAAM,WACnD,SAAU,IAAMa,EAAM,aAAa,CAACA,EAAM,MAAM,KAAK,EACrD,OAAQA,EAAM,WACb,GAAGb,CAAA,CAAA,CAGhB"}
1
+ {"version":3,"file":"checkbox.js","sources":["../../lib/components/checkbox.tsx"],"sourcesContent":["import {\n Checkbox as AriaCheckbox,\n CheckboxGroup as AriaCheckboxGroup,\n composeRenderProps,\n type CheckboxProps as AriaCheckboxProps,\n} from 'react-aria-components';\n\nimport { FormField, labelVariants, type FormFieldProps } from '../components/field';\nimport { useFieldContext } from '../utilities/form-context';\nimport { classNames } from '../utilities/theme';\nimport { IcCheck, IcMinus } from './icons';\n\nexport const CheckboxGroup = AriaCheckboxGroup;\ntype CheckboxProps = AriaCheckboxProps & FormFieldProps;\nexport function Checkbox({ className, label, description, errorMessage, ...props }: Omit<CheckboxProps, 'children'>) {\n return (\n <div className=\"group form-field\">\n <FormField label={label} description={description} errorMessage={errorMessage}>\n <AriaCheckbox\n className={composeRenderProps(className, className =>\n classNames(\n 'group/checkbox cursor-pointer focus-ring flex items-center gap-x-2',\n /* Disabled */\n 'disabled-muted',\n labelVariants,\n className\n )\n )}\n {...props}\n >\n {composeRenderProps(<></>, (_, renderProps) => (\n <>\n <div\n className={classNames(\n 'flex size-input shrink-0 items-center bg-popover justify-center border border-input text-current ring-offset-background',\n /* Selected */\n 'group-data-[indeterminate]/checkbox:bg-primary group-data-[selected]/checkbox:bg-primary group-data-[indeterminate]/checkbox:text-primary-foreground group-data-[selected]/checkbox:text-primary-foreground',\n /* Disabled */\n 'group-data-[disabled]/checkbox:cursor-not-allowed group-data-[disabled]/checkbox:opacity-50',\n /* Invalid */\n 'group-data-[invalid]/checkbox:border-destructive group-data-[invalid]/checkbox:group-data-[selected]/checkbox:bg-destructive group-data-[invalid]/checkbox:group-data-[selected]/checkbox:text-destructive-foreground',\n /* Resets */\n 'focus:outline-none focus-visible:outline-none'\n )}\n >\n {renderProps.isIndeterminate ? (\n <IcMinus className=\"size-icon\" />\n ) : renderProps.isSelected ? (\n <IcCheck className=\"size-icon\" />\n ) : null}\n </div>\n </>\n ))}\n </AriaCheckbox>\n </FormField>\n </div>\n );\n}\n\nexport type TfCheckboxProps = Omit<React.ComponentProps<typeof Checkbox>, 'onChange' | 'onBlur' | 'isChecked'>;\nexport function TfCheckbox({ ...props }: TfCheckboxProps) {\n const field = useFieldContext<boolean>({ disabled: props.isDisabled });\n return (\n <Checkbox\n isSelected={field.state.value}\n isDisabled={field.form.state.isSubmitting || props.isDisabled}\n onChange={() => field.handleChange(!field.state.value)}\n onBlur={field.handleBlur}\n {...props}\n />\n );\n}\n"],"names":["CheckboxGroup","AriaCheckboxGroup","Checkbox","className","label","description","errorMessage","props","jsx","FormField","AriaCheckbox","composeRenderProps","classNames","labelVariants","Fragment","_","renderProps","IcMinus","IcCheck","TfCheckbox","field","useFieldContext"],"mappings":"ycAYO,MAAMA,EAAgBC,EAEtB,SAASC,EAAS,CAAE,UAAAC,EAAW,MAAAC,EAAO,YAAAC,EAAa,aAAAC,EAAc,GAAGC,GAA0C,CACjH,OACIC,EAAC,OAAI,UAAU,mBACX,WAACC,EAAA,CAAU,MAAAL,EAAc,YAAAC,EAA0B,aAAAC,EAC/C,SAAAE,EAACE,EAAA,CACG,UAAWC,EAAmBR,EAAWA,GACrCS,EACI,qEAEA,iBACAC,EACAV,CAAA,CACJ,EAEH,GAAGI,EAEH,WAAmBC,EAAAM,EAAA,CAAA,CAAE,EAAK,CAACC,EAAGC,IAC3BR,EAAAM,EAAA,CACI,SAAAN,EAAC,MAAA,CACG,UAAWI,EACP,0HAEA,+MAEA,8FAEA,wNAEA,+CAAA,EAGH,SAAAI,EAAY,gBACTR,EAACS,EAAA,CAAQ,UAAU,WAAA,CAAY,EAC/BD,EAAY,WACZR,EAACU,EAAA,CAAQ,UAAU,YAAY,EAC/B,IAAA,CAAA,EAEZ,CACH,CAAA,CAAA,EAET,CAAA,CACJ,CAER,CAGO,SAASC,EAAW,CAAE,GAAGZ,GAA0B,CACtD,MAAMa,EAAQC,EAAyB,CAAE,SAAUd,EAAM,WAAY,EACrE,OACIC,EAACN,EAAA,CACG,WAAYkB,EAAM,MAAM,MACxB,WAAYA,EAAM,KAAK,MAAM,cAAgBb,EAAM,WACnD,SAAU,IAAMa,EAAM,aAAa,CAACA,EAAM,MAAM,KAAK,EACrD,OAAQA,EAAM,WACb,GAAGb,CAAA,CAAA,CAGhB"}
@@ -1,4 +1,4 @@
1
- import { operations } from '@cryptlex/web-api-types';
1
+ import { operations } from '@cryptlex/web-api-types/develop';
2
2
  import { MultiSelectProps } from '../components/multi-select';
3
3
  import { ApiFilters } from '../utilities/resources';
4
4
  import { TfMultipleIdSearchInput } from './id-search';
@@ -1,2 +1,2 @@
1
- import"react/jsx-runtime";import"react";import"./button.js";import{C as z,D as G,F as H}from"./data-table.js";import"./date-picker.js";import"./menu.js";import"./popover.js";import"../utilities/form-hook.js";import"../utilities/resources.js";import"../utilities/theme.js";import"./icons.js";import"./id-search.js";import"class-variance-authority";import"react-aria-components";import"./loader.js";import"clsx";import"@dnd-kit/core";import"@dnd-kit/sortable";import"@dnd-kit/utilities";import"@tanstack/react-query";import"@tanstack/react-table";import"@uidotdev/usehooks";import"lodash-es";import"./searchfield.js";import"./field.js";import"./table.js";import"../utilities/date.js";import"./checkbox.js";import"../utilities/form.js";import"../utilities/form-context.js";import"@tanstack/react-form";import"@internationalized/date";import"./calendar.js";import"./datefield.js";import"./list-box.js";import"./select.js";import"./multi-select.js";import"./numberfield.js";import"./textfield.js";import"../utilities/string.js";export{z as COMPARISON_OPERATOR_LABELS,G as DataTableFilter,H as FILTER_COMPARISON_OPERATORS};
1
+ import"react/jsx-runtime";import"react";import"./button.js";import{C as z,D as G,F as H}from"./data-table.js";import"./date-picker.js";import"./menu.js";import"./popover.js";import"../utilities/form-hook.js";import"../utilities/resources.js";import"../utilities/theme.js";import"./icons.js";import"./id-search.js";import"class-variance-authority";import"react-aria-components";import"./loader.js";import"clsx";import"@dnd-kit/core";import"@dnd-kit/sortable";import"@dnd-kit/utilities";import"@tanstack/react-query";import"@tanstack/react-table";import"@uidotdev/usehooks";import"lodash-es";import"./searchfield.js";import"./field.js";import"./table.js";import"../utilities/date.js";import"./checkbox.js";import"../utilities/form-context.js";import"@tanstack/react-form";import"@internationalized/date";import"./calendar.js";import"./datefield.js";import"../utilities/form.js";import"./list-box.js";import"./select.js";import"./multi-select.js";import"./numberfield.js";import"./textfield.js";import"../utilities/string.js";export{z as COMPARISON_OPERATOR_LABELS,G as DataTableFilter,H as FILTER_COMPARISON_OPERATORS};
2
2
  //# sourceMappingURL=data-table-filter.js.map
@@ -1,4 +1,4 @@
1
- import { operations } from '@cryptlex/web-api-types';
1
+ import { operations } from '@cryptlex/web-api-types/develop';
2
2
  import { ColumnDef, ColumnHelper, PaginationState, SortingState } from '@tanstack/react-table';
3
3
  import { PressEvent } from 'react-aria-components';
4
4
  import { FiltersConfig, TableFilter } from '../components/data-table-filter';
@@ -1 +1 @@
1
- {"version":3,"file":"data-table.js","sources":["../../lib/components/data-table.tsx","../../lib/components/data-table-filter.tsx"],"sourcesContent":["'use client';\nimport type { operations } from '@cryptlex/web-api-types';\nimport {\n closestCenter,\n DndContext,\n DragOverlay,\n KeyboardSensor,\n PointerSensor,\n useSensor,\n useSensors,\n} from '@dnd-kit/core';\nimport {\n arrayMove,\n SortableContext,\n sortableKeyboardCoordinates,\n useSortable,\n verticalListSortingStrategy,\n} from '@dnd-kit/sortable';\nimport { CSS } from '@dnd-kit/utilities';\nimport { keepPreviousData, useQuery } from '@tanstack/react-query';\nimport {\n type AccessorFnColumnDef,\n type Column,\n type ColumnDef,\n type ColumnHelper,\n type ColumnOrderState,\n createColumnHelper,\n flexRender,\n getCoreRowModel,\n type PaginationState,\n type RowSelectionState,\n type SortingState,\n type Updater,\n useReactTable,\n type VisibilityState,\n} from '@tanstack/react-table';\nimport { useLocalStorage } from '@uidotdev/usehooks';\nimport { merge } from 'lodash-es';\nimport { createContext, useContext, useEffect, useMemo, useState } from 'react';\nimport type { PressEvent } from 'react-aria-components';\nimport { Button } from '../components/button';\nimport { DataTableFilter, type FiltersConfig, type TableFilter } from '../components/data-table-filter';\nimport { Loader } from '../components/loader';\nimport { EasyMenu, MenuItem } from '../components/menu';\nimport { SearchField } from '../components/searchfield';\nimport { TableBody, TableCell, Table as TableComponent, TableHead, TableHeader, TableRow } from '../components/table';\nimport { formatDate } from '../utilities/date';\nimport type { ApiSchema, CtxResourceName } from '../utilities/resources';\nimport { useResourceFormatter } from '../utilities/resources';\nimport { classNames } from '../utilities/theme';\nimport { Checkbox } from './checkbox';\nimport {\n type CtxIcon,\n IcColumns,\n IcFirst,\n IcGrip,\n IcInfo,\n IcLast,\n IcLeft,\n IcMoreVertical,\n IcRefresh,\n IcRight,\n IcSortAsc,\n IcSortDesc,\n IcSortNone,\n} from './icons';\n\n/** Reserved name for actions column */\n// export const ACTIONS_COLUMN_ID = 'tableActions';\n\nexport type TableAction<in TActionData> = {\n onClick: (e: PressEvent, t: TActionData[]) => void;\n bulk: boolean;\n icon: CtxIcon;\n tooltip?: string;\n};\n\nexport type TableFetchFn<in out TData extends object> = (\n p: PaginationState,\n s: SortingState,\n q: string,\n f: Record<string, any>\n) => Promise<{\n total: number;\n data: TData[] | undefined;\n}>;\nexport function getTableCallback<T extends object>(\n getter: (\n q: Record<string, any>\n ) => Promise<{ data?: T[]; error?: { code?: string | null; message: string }; response: Response }>\n): { callback: TableFetchFn<T>; columnHelper: ColumnHelper<T> } {\n const callback: TableFetchFn<T> = async (pagination, sorting, searching, filters) => {\n const query = {\n ...filters,\n page: pagination.pageIndex + 1,\n limit: pagination.pageSize,\n sort: generateSortParam(sorting[0]),\n search: searching,\n };\n\n const _f = await getter(query);\n\n return {\n total: Number.parseInt(_f.response.headers.get('Pagination-Count') || '0'),\n data: _f.data,\n };\n };\n\n const columnHelper = createColumnHelper<T>();\n\n return { callback, columnHelper };\n}\n\nfunction generateSortParam(sort: { id: string; desc: boolean } | undefined): string {\n if (sort) {\n if (sort.desc) {\n return `-${sort.id}`;\n } else {\n return `+${sort.id}`;\n }\n } else {\n return '-createdAt';\n }\n}\n\nconst cH = createColumnHelper<any>();\nconst TABLE_CHECK_BOX_COLUMN = [\n cH.accessor('checkbox', {\n header: ({ table }) => (\n <Checkbox\n isIndeterminate={table.getIsSomeRowsSelected() && !table.getIsAllPageRowsSelected()}\n isSelected={table.getIsAllPageRowsSelected() || table.getIsSomePageRowsSelected()}\n onChange={() => table.toggleAllPageRowsSelected()}\n aria-label=\"Select all\"\n />\n ),\n\n cell: ({ row }) => (\n <Checkbox isSelected={row.getIsSelected()} onChange={() => row.toggleSelected()} aria-label=\"Select row\" />\n ),\n enableSorting: false,\n enableHiding: false,\n }),\n];\n\nconst TABLE_ID_COLUMN = [\n cH.accessor('id', {\n header: () => 'ID',\n }),\n];\nconst TABLE_DEFAULT_DATE_COLUMNS = [\n cH.accessor('createdAt', {\n header: () => 'Creation Date',\n cell: ({ row }) => {\n const date = row.getValue('createdAt') satisfies string | null | undefined;\n return formatDate(date);\n },\n enableHiding: false,\n }),\n cH.accessor('updatedAt', {\n header: () => 'Last Updated',\n cell: ({ row }) => {\n const date = row.getValue('updatedAt') satisfies string | null | undefined;\n return formatDate(date);\n },\n enableHiding: false,\n }),\n];\n\nconst ACTIONS_COLUMN_ID = 'TableActions';\nconst getActionColumn = (rowActions: RowAction<any>[]) => {\n if (rowActions.length === 0) return [];\n\n return [\n cH.accessor(ACTIONS_COLUMN_ID, {\n header: '',\n id: ACTIONS_COLUMN_ID,\n enableHiding: false,\n cell: ({ row }) => (\n <EasyMenu label={<IcMoreVertical />} size={'icon'}>\n {rowActions.map(ra => (\n <MenuItem isDisabled={ra.disabled(row.original)} onPress={() => ra.onPress(row.original)}>\n {ra.label}\n </MenuItem>\n ))}\n </EasyMenu>\n ),\n }),\n ];\n};\n\ntype RowAction<T> = {\n onPress: (t: T) => void;\n label: React.ReactElement;\n disabled: (t: T) => boolean;\n};\n\ntype DataTableFactory<T extends object, TOperation extends keyof operations> = {\n resourceName: CtxResourceName;\n callback: TableFetchFn<T>;\n columns: ColumnDef<T, any>[];\n tableActions: TableAction<T>[];\n columnsToHideByDefault?: Partial<Record<keyof T, boolean>>; // Columns that are hidden by default\n allowSelection?: boolean;\n filterConfig: FiltersConfig<TOperation>;\n initialFilters: TableFilter[];\n rowActions?: RowAction<T>[];\n};\n\ntype DataTableState = {\n sorting: SortingState;\n pagination: PaginationState;\n};\n/**\n * Hook for handling all data-table state. Used in DataTableContext\n */\nexport function useDataTableState<T extends object, TOperation extends keyof operations>({\n resourceName,\n columns,\n callback,\n filterConfig,\n columnsToHideByDefault = {},\n allowSelection = false,\n initialFilters = [],\n tableActions,\n rowActions,\n}: DataTableFactory<T, TOperation>) {\n const [tableState, _setTableState] = useState<DataTableState>({\n /** Reflect in URL in host application */\n pagination: { pageIndex: 0, pageSize: 20 }, // Pagination state\n sorting: [], // Sorting state\n });\n //\n const [rowSelection, setRowSelection] = useState<RowSelectionState>({});\n\n /** Reflect in URL in host application */\n const [searchQuery, setSearchQuery] = useState('');\n\n const [columnOrder, setColumnOrder] = useLocalStorage<ColumnOrderState>(\n `${resourceName}_ctx_column_order_preference`,\n []\n );\n const [columnVisibility, setColumnVisibility] = useLocalStorage<VisibilityState>(\n `${resourceName}_ctx_column_visibility_preference`,\n {\n id: false,\n ...columnsToHideByDefault,\n }\n );\n\n const [filters, setFilters] = useState(initialFilters);\n\n const mergedFilters = useMemo(() => {\n // TODO, generic transform fn\n return filters\n .map(tf => {\n if (Array.isArray(tf.value)) {\n return {\n [tf.property]: {\n [tf.operator]: tf.value.join(','),\n },\n };\n }\n return {\n [tf.property]: {\n [tf.operator]: tf.value,\n },\n };\n })\n .reduce((acc, current) => {\n return merge(acc, current);\n }, {});\n }, [filters]);\n\n // Update table state with new values\n const updateTableState = (updates: Partial<DataTableState>) => {\n _setTableState(prev => ({ ...prev, ...updates }));\n };\n\n const { sorting, pagination } = tableState;\n\n const query = useQuery({\n queryKey: [resourceName, pagination, sorting, searchQuery, mergedFilters],\n queryFn: () => callback(pagination, sorting, searchQuery, mergedFilters),\n placeholderData: keepPreviousData, // Keep previous data while loading new data\n retry: 0,\n refetchOnWindowFocus: false,\n });\n\n const metadataColumns = useMemo<AccessorFnColumnDef<any, string>[]>(() => {\n const data = query.data?.data;\n if (!data?.length) return [];\n\n type WithMeta = T & { metadata: ApiSchema<'MetadataDto'>[] };\n const rowHasMetadata = (row: Record<string, any>): row is WithMeta =>\n row != null && typeof row === 'object' && 'metadata' in row && Array.isArray(row.metadata);\n\n const rowsWithMeta = data.filter(rowHasMetadata);\n if (rowsWithMeta.length === 0) return [];\n const keys: string[] = Array.from(new Set(rowsWithMeta.flatMap(r => r.metadata?.map(m => m.key) ?? [])));\n\n return keys.map(key =>\n cH.accessor(\n row => {\n if (rowHasMetadata(row)) {\n return row?.metadata?.find(m => m.key === key)?.value ?? '';\n }\n return '';\n },\n {\n id: key,\n header: key, // tooltip header\n enableSorting: false,\n cell: info => {\n const value = info.getValue();\n // Handle null/undefined values\n if (value === null || value === undefined) return '';\n // For primitive types, return the string representation\n return String(value);\n },\n }\n )\n );\n }, [query.data?.data]);\n\n /**\n * ID,createdAt and updatedAt will be added by default for all tables\n * If selection is allowed, checkbox will be added\n * If the dto has metadata, dynamics columns for all the metadata key-value will be added(particular for a view)\n * If there are actions for the table, they will be placed fixed at the right side of table.\n */\n const cols: ColumnDef<any, any>[] = [\n ...(allowSelection ? TABLE_CHECK_BOX_COLUMN : []),\n ...TABLE_ID_COLUMN,\n ...columns,\n ...(metadataColumns.length ? metadataColumns : []),\n ...TABLE_DEFAULT_DATE_COLUMNS,\n ...getActionColumn(rowActions ?? []),\n ];\n\n // Type-guard for updater\n function isUpdaterFunction<T>(updater: Updater<T>): updater is (old: T) => T {\n return typeof updater === 'function';\n }\n // Utility function to resolve updater\n function resolveUpdater<T>(updater: Updater<T>, currentValue: T) {\n if (isUpdaterFunction(updater)) {\n return updater(currentValue);\n }\n return updater;\n }\n\n // Use react-table's hook to create the table instance\n const tanTable = useReactTable({\n data: query.data?.data ?? [],\n columns: cols,\n getCoreRowModel: getCoreRowModel(),\n rowCount: query.data?.total,\n manualPagination: true, // Handle pagination manually since pagination is done server side for data tables\n onPaginationChange: updater => {\n updateTableState({ pagination: resolveUpdater(updater, pagination) });\n },\n manualSorting: true, // Handle sorting manually since sorting is done server side for data tables\n onSortingChange: updater => {\n setRowSelection({});\n updateTableState({ sorting: [...resolveUpdater(updater, sorting)] }); // Reset selection when sorting.\n },\n manualFiltering: true, // Handle filtering manually since filtering is done server side for data tables\n onColumnVisibilityChange: updater => {\n setColumnVisibility(resolveUpdater(updater, columnVisibility));\n },\n onRowSelectionChange: updater => {\n setRowSelection(resolveUpdater(updater, rowSelection));\n },\n onColumnOrderChange: updater => {\n setColumnOrder(resolveUpdater(updater, columnOrder));\n },\n state: {\n sorting: sorting,\n columnVisibility: columnVisibility,\n pagination: pagination,\n rowSelection: rowSelection,\n columnOrder: columnOrder,\n },\n meta: {\n refetch: query.refetch,\n },\n });\n\n // By default, ColumnDef does not give guarantees of column.id existing. Once useReactTable is called, all columns are assigned IDs.\n // This populates the columnIds in the columnOrder state\n useEffect(() => {\n setColumnOrder([...tanTable.getAllLeafColumns().map(c => c.id)]);\n }, []);\n\n return {\n tableState,\n updateTableState,\n query,\n setSearchQuery,\n searchQuery,\n tanTable,\n mergedFilters,\n filters,\n setFilters,\n filterConfig,\n tableActions,\n } as const;\n}\n\nexport const DataTableContext = createContext<ReturnType<typeof useDataTableState> | null>(null);\n// TODO, don't export this\nexport function useDataTable() {\n const ctx = useContext(DataTableContext);\n if (!ctx) {\n throw Error('DataTable should be used within DataTableProvider.');\n }\n return ctx;\n}\n\nexport function DataTableProvider<T extends object, TOperation extends keyof operations>({\n children,\n ...props\n}: { children: React.ReactNode } & ReturnType<typeof useDataTableState<T, TOperation>>) {\n // @ts-expect-error, propogating the generic type further will be more complex. Since this is a tightly coupled type, it should be okay but reviewed whenever useDataTableState changes.\n return <DataTableContext.Provider value={props}>{children}</DataTableContext.Provider>;\n}\n\nexport type DataTableProps = React.ComponentProps<'section'>;\nexport function DataTable({ className, ...props }: DataTableProps) {\n const { query, tanTable } = useDataTable();\n\n return (\n <>\n {/* Table Actions Section */}\n <section {...props} className={classNames('flex flex-col bg-card', className)}>\n <Actions />\n {/* The div here is necessary because TableContent is internally a <table> tag and does not respect width, height CSS */}\n <div className=\"w-full overflow-auto border-x grow min-h-table relative\" tabIndex={0}>\n {/* Table overlay with loader */}\n {query.isLoading && (\n <TableOverlay className=\"cursor-wait\">\n <Loader />\n </TableOverlay>\n )}\n {/* Table overlay for empty table */}\n {!query.isLoading && tanTable.getRowModel().rows.length === 0 && (\n // Empty table\n <TableOverlay className=\"cursor-not-allowed\">\n {!query.isFetching &&\n (query.isError ? (\n <span className=\"flex gap-3 justify-center items-center\">\n {/* TODO (mudasir-pandith) Check for 403 explicitly!! */}\n {/* <span>{query.error}</span> */}\n <IcInfo />\n <span>{query.error.message}</span>\n </span>\n ) : query.data?.data?.length === 0 ? (\n <>No results found.</>\n ) : (\n <>Unknown error. Please contact customer support.</>\n ))}\n </TableOverlay>\n )}\n {!query.isLoading && tanTable.getRowModel().rows.length !== 0 && (\n <TableContent className=\"size-full\" />\n )}\n </div>\n\n {/* Table Footer Section with Pagination and Column Picker */}\n <div className=\"flex w-full justify-between border gap-icon p-icon overflow-x-auto\">\n <div className=\"flex gap-icon\">\n <ColumnPicker />\n <PageSize />\n </div>\n <Paginator />\n </div>\n </section>\n </>\n );\n}\n/** Table overlay to be shown for loaders or other messages */\nfunction TableOverlay({ children, className }: { children: React.ReactNode; className?: string }) {\n return (\n <>\n <span\n className={classNames(\n className,\n 'absolute top-0 bg-card z-20 size-full body-sm flex items-center justify-center'\n )}\n >\n {children}\n </span>\n {/* Keep something in document flow with the correct height */}\n <span className=\"relative h-full w-0 block\" />\n </>\n );\n}\n\nfunction ColumnPicker() {\n const { tanTable } = useDataTable();\n const [activeId, setActiveId] = useState<string | null>(null);\n\n const resourceFormatter = useResourceFormatter();\n\n const sensors = useSensors(\n useSensor(PointerSensor),\n useSensor(KeyboardSensor, {\n coordinateGetter: sortableKeyboardCoordinates,\n })\n );\n return (\n <DndContext\n sensors={sensors}\n collisionDetection={closestCenter}\n onDragStart={event => {\n const { active } = event;\n setActiveId(active.id.toString());\n }}\n onDragEnd={event => {\n const { active, over } = event;\n\n if (over && active.id !== over.id) {\n const columnOrder = tanTable.getState().columnOrder;\n const oldIndex = columnOrder.indexOf(active.id.toString());\n const newIndex = columnOrder.indexOf(over.id.toString());\n tanTable.setColumnOrder([...arrayMove(columnOrder, oldIndex, newIndex)]);\n }\n\n setActiveId(null);\n }}\n >\n <SortableContext items={tanTable.getState().columnOrder} strategy={verticalListSortingStrategy}>\n <EasyMenu\n label={\n <>\n <IcColumns />\n Columns\n </>\n }\n selectionMode=\"multiple\"\n items={tanTable.getAllFlatColumns()}\n // Using selectedKeys = 'all' does not mark MenuItems with isDisabled=true as selected. This is not the intended behaviour in this use-case.\n selectedKeys={tanTable.getVisibleFlatColumns().map(c => c.id)}\n >\n <MenuItem onAction={() => tanTable.toggleAllColumnsVisible()} className={'italic'}>\n (select all)\n </MenuItem>\n {tanTable.getState().columnOrder.map(colId => {\n const col = tanTable.getAllFlatColumns().find(c => c.id === colId);\n if (!col) return null;\n return <SortableItem key={col.id} column={col} />;\n })}\n </EasyMenu>\n <DragOverlay>\n {activeId ? (\n <div className=\"opacity-70 border-2 border-primary\">{resourceFormatter(activeId)}</div>\n ) : null}\n </DragOverlay>\n </SortableContext>\n </DndContext>\n );\n\n function SortableItem({ column }: { column: Column<any, unknown> }) {\n const { attributes, listeners, setNodeRef, transform, transition } = useSortable({ id: column.id });\n const style = {\n transform: CSS.Transform.toString(transform),\n transition,\n zIndex: '999',\n };\n return (\n <MenuItem\n ref={setNodeRef}\n style={style}\n {...attributes}\n id={column.id}\n onAction={() => column.toggleVisibility()}\n isDisabled={!column.getCanHide()}\n className=\"flex items-center\"\n >\n <IcGrip {...listeners} className=\"size-icon cursor-grab\" />\n {resourceFormatter(column.id)}\n {column.getIsSorted() && <SortIcon className=\"size-icon\" direction={column.getIsSorted()} />}\n </MenuItem>\n );\n }\n}\n\nfunction Paginator() {\n const { tanTable, query } = useDataTable();\n const rowCount = query.data?.total ?? 0;\n return (\n <div className=\"flex items-center gap-2\">\n <span className=\"whitespace-nowrap body-sm text-muted\">\n {`${tanTable.getState().pagination.pageIndex * tanTable.getState().pagination.pageSize + 1} - ${Math.min(\n (tanTable.getState().pagination.pageIndex + 1) * tanTable.getState().pagination.pageSize,\n rowCount\n )} of ${rowCount?.toLocaleString()}`}\n </span>\n\n <Button\n onPress={() => tanTable.firstPage()}\n isDisabled={!tanTable.getCanPreviousPage()}\n variant=\"neutral\"\n size={'icon'}\n >\n <IcFirst />\n </Button>\n <Button\n onPress={() => tanTable.previousPage()}\n isDisabled={!tanTable.getCanPreviousPage()}\n variant=\"neutral\"\n size={'icon'}\n >\n <IcLeft />\n </Button>\n <Button\n onPress={() => tanTable.nextPage()}\n isDisabled={!tanTable.getCanNextPage()}\n variant=\"neutral\"\n size={'icon'}\n >\n <IcRight />\n </Button>\n <Button\n onClick={() => tanTable.lastPage()}\n isDisabled={!tanTable.getCanNextPage()}\n variant=\"neutral\"\n size={'icon'}\n >\n <IcLast />\n </Button>\n </div>\n );\n}\n\nfunction PageSize() {\n const { tanTable } = useDataTable();\n const PAGE_SIZES = [10, 20, 30, 40, 50];\n\n return (\n <EasyMenu\n label={tanTable.getState().pagination.pageSize.toString()}\n selectionMode=\"single\"\n selectedKeys={[tanTable.getState().pagination.pageSize.toString()]}\n items={PAGE_SIZES.map(s => ({ id: s.toString(), value: s }))}\n >\n {items => <MenuItem onAction={() => tanTable.setPageSize(items.value)}>{items.value}</MenuItem>}\n </EasyMenu>\n );\n}\n\nfunction Actions() {\n const { query, tanTable, searchQuery, setSearchQuery, tableActions } = useDataTable();\n\n return (\n <section className=\"flex bg-card justify-between my-0 p-icon border gap-icon overflow-auto\">\n <div className=\"flex gap-icon\">\n <Button isPending={query.isFetching} onClick={() => query.refetch()} variant={'neutral'} size={'icon'}>\n <IcRefresh />\n </Button>\n\n {tableActions\n .filter(ta => ta.bulk === tanTable.getSelectedRowModel().rows.length > 0)\n .map((ta, i) => {\n const Icon = ta.icon;\n return (\n <Button\n key={`${i}-${ta.bulk}`}\n type=\"button\"\n isDisabled={query.isFetching}\n className=\"animate-in fade-in slide-in-from-left-15 duration-300 transition-transform\"\n onPress={e => {\n ta.onClick(\n e,\n tanTable.getSelectedRowModel().rows.map(r => r.original)\n );\n }}\n size={'icon'}\n >\n <Icon />\n </Button>\n );\n })}\n </div>\n <div className=\"flex gap-icon\">\n <DataTableFilter />\n {<SearchField value={searchQuery} onChange={setSearchQuery} />}\n </div>\n </section>\n );\n}\n\nfunction SortIcon({\n direction,\n ...props\n}: { direction: 'asc' | 'desc' | false } & Omit<React.ComponentProps<'svg'>, 'direction'>) {\n if (direction === 'asc') return <IcSortAsc className=\"size-3.5\" {...props} />;\n else if (direction === 'desc') return <IcSortDesc className=\"size-3.5\" {...props} />;\n else return <IcSortNone className=\"size-3.5\" {...props} />;\n}\n\n// TODO, automate checking valid HTML\nfunction TableContent({ className }: React.ComponentProps<typeof TableComponent>) {\n const { tanTable } = useDataTable();\n const resourceFormatter = useResourceFormatter();\n const tableCellStyle = (isSticky: boolean, className?: string) =>\n classNames(\n 'px-icon py-2 text-left body-sm font-medium whitespace-nowrap',\n isSticky && 'bg-card sticky right-0 z-50 text-center',\n className\n );\n return (\n <TableComponent className={classNames(className)}>\n <TableHeader className=\"sticky top-0 z-10\">\n {tanTable.getHeaderGroups().map(headerGroup => (\n <TableRow key={headerGroup.id}>\n {headerGroup.headers.map(header => (\n <TableHead\n key={header.id}\n colSpan={header.colSpan}\n className={tableCellStyle(false, 'bg-card')}\n >\n {!header.column.getCanSort() &&\n !header.isPlaceholder &&\n flexRender(header.column.columnDef.header, header.getContext())}\n {header.column.getCanSort() && (\n <Button\n variant=\"ghost\"\n className=\"w-full justify-start px-1.5\"\n onPress={header.column.getToggleSortingHandler()}\n >\n <span>{resourceFormatter(header.id)}</span>\n <SortIcon direction={header.column.getIsSorted()} />\n </Button>\n )}\n </TableHead>\n ))}\n </TableRow>\n ))}\n </TableHeader>\n <TableBody className=\"flex-1 overflow-y-auto relative\">\n {tanTable.getRowModel().rows.map(row => (\n <TableRow\n className={classNames(\n 'transition-colors data-[selected=true]:bg-primary/10 hover:bg-muted-foreground/20'\n )}\n key={row.id}\n data-selected={row.getIsSelected()}\n >\n {row.getVisibleCells().map(cell => (\n <TableCell key={cell.id} className={tableCellStyle(cell.column.id === ACTIONS_COLUMN_ID)}>\n {flexRender(cell.column.columnDef.cell, cell.getContext())}\n </TableCell>\n ))}\n </TableRow>\n ))}\n </TableBody>\n </TableComponent>\n );\n}\n","'use client';\nimport type { operations } from '@cryptlex/web-api-types';\nimport { useRef } from 'react';\nimport { Button } from '../components/button';\nimport { useDataTable } from '../components/data-table';\nimport { TfDatePicker } from '../components/date-picker';\nimport { EasyMenu, MenuItem } from '../components/menu';\nimport type { MultiSelectProps } from '../components/multi-select';\nimport { Popover, PopoverTrigger } from '../components/popover';\nimport { useAppForm } from '../utilities/form-hook';\nimport { useResourceFormatter, type ApiFilters } from '../utilities/resources';\nimport { classNames } from '../utilities/theme';\nimport { IcFilter, IcRemove } from './icons';\nimport { TfMultipleIdSearchInput } from './id-search';\n\nexport const FILTER_COMPARISON_OPERATORS = [\n 'eq',\n 'ne',\n 'cn',\n 'nc',\n 'sw',\n 'ew',\n 'in',\n 'nin',\n 'gt',\n 'gte',\n 'lt',\n 'lte',\n] as const;\nexport type FilterComparisonOperator = (typeof FILTER_COMPARISON_OPERATORS)[number];\n\nexport const COMPARISON_OPERATOR_LABELS: Record<FilterComparisonOperator, string> = {\n eq: 'equal to',\n ne: 'not equal to',\n cn: 'contains',\n nc: 'does not contain',\n sw: 'starts with',\n ew: 'ends with',\n in: 'includes',\n nin: 'does not include',\n gt: 'greater than',\n gte: 'greater than or equal to',\n lt: 'less than',\n lte: 'less than or equal to',\n};\n\ntype BaseLocalFilter<T extends FilterType, V> = {\n id: string;\n type: T;\n property: string;\n operator: FilterComparisonOperator;\n value: V | undefined;\n displayValue?: string;\n};\ntype EnumLocalFilter = BaseLocalFilter<'enum', Set<string | number>>;\ntype IdLocalFilter = BaseLocalFilter<'id', string>;\ntype BoolLocalFilter = BaseLocalFilter<'bool', boolean>;\ntype StringLocalFilter = BaseLocalFilter<'string', string>;\ntype NumberLocalFilter = BaseLocalFilter<'number', number>;\n// DatePicker accepts a string,and converts it to a ZonedDateTime\ntype DateLocalFilter = BaseLocalFilter<'date', string>;\ntype IdSearchLocalFilter = BaseLocalFilter<'id-search', Set<string | number>>;\n\nfunction createNewFilter(type: FilterType, property: string): TableFilter {\n const id = `${property}-${Date.now()}`;\n const operator = FilterOperations[type][0];\n\n switch (type) {\n case 'bool':\n return { id, type, property, operator, value: true };\n case 'string':\n return { id, type, property, operator, value: '' };\n case 'date':\n return { id, type, property, operator, value: new Date().toISOString() };\n case 'id':\n return { id, type, property, operator, value: '' };\n case 'id-search':\n return { id, type, property, operator, value: new Set<string | number>() };\n case 'enum':\n return { id, type, property, operator, value: new Set<string | number>() };\n case 'number':\n return { id, type, property, operator, value: 0 };\n }\n}\n\nexport type TableFilter =\n | EnumLocalFilter\n | IdLocalFilter\n | BoolLocalFilter\n | StringLocalFilter\n | DateLocalFilter\n | IdSearchLocalFilter\n | NumberLocalFilter;\n\nexport type FilterConfig =\n | { type: 'enum'; options: MultiSelectProps['items'] }\n | ({ type: 'id-search' } & Pick<React.ComponentProps<typeof TfMultipleIdSearchInput>, 'accessor' | 'searchFn'>)\n | { type: 'id' }\n | { type: 'bool' }\n | { type: 'string' }\n | { type: 'date' }\n | { type: 'number' };\n\nexport type FilterType = FilterConfig['type'];\n\nconst FilterOperations: Record<FilterType, FilterComparisonOperator[]> = {\n bool: ['eq'],\n enum: ['in', 'nin'],\n id: ['in', 'nin'],\n 'id-search': ['in', 'nin'],\n string: ['eq', 'ne', 'cn', 'nc', 'sw', 'ew', 'in', 'nin'],\n date: ['lt', 'gt'],\n number: ['eq', 'ne', 'gt', 'gte', 'lt', 'lte'],\n};\n\n// TS workaround to get rid of filterConfig: Required<Record<never, FilterConfig>>\nexport type FiltersConfig<TOperation extends keyof operations> = [keyof ApiFilters<TOperation>] extends [never]\n ? Record<string, FilterConfig>\n : Required<Record<keyof ApiFilters<TOperation>, FilterConfig>>;\n\nexport function DataTableFilter({ className, ...props }: React.ComponentProps<'section'>) {\n const { filters, query, setFilters, filterConfig } = useDataTable();\n\n const addFilterButtonRef = useRef<HTMLButtonElement>(null);\n\n const resourceFormatter = useResourceFormatter();\n\n const DEFAULT_VALUES: { filters: TableFilter[] } = {\n filters,\n };\n const form = useAppForm({\n defaultValues: DEFAULT_VALUES,\n onSubmit: ({ value }) => {\n setFilters(value.filters);\n },\n });\n\n // More reason to hate TS https://github.com/Microsoft/TypeScript/issues/12870\n const filterKeys = Object.keys(filterConfig).sort();\n\n return (\n <section {...props} className={classNames('flex gap-icon items-center', className)}>\n <PopoverTrigger\n onOpenChange={o => {\n // Set filters when the popover closes\n if (!o) {\n form.handleSubmit();\n } else {\n addFilterButtonRef.current?.focus();\n }\n }}\n >\n <div className=\"relative\">\n {filters.length > 0 && (\n <div className=\"size-2 rounded-full absolute bg-destructive z-20 top-0 right-0 translate-x-0.5 -translate-y-0.5\"></div>\n )}\n <Button\n isDisabled={query.isPending || filterKeys.length === 0}\n type=\"button\"\n size={'icon'}\n variant={'neutral'}\n >\n <IcFilter />\n </Button>\n </div>\n {/* TODO, icon maps with dynamic imports? */}\n {/* TODO open popover with form for property specific filter */}\n {/* TODO, icons here??? */}\n <Popover className=\"w-full p-icon\">\n <form\n onSubmit={e => {\n e.preventDefault();\n }}\n className=\"flex flex-col gap-icon max-h-table overflow-auto \"\n >\n <form.Field mode=\"array\" name={'filters'}>\n {field => {\n return (\n <>\n {field.state.value.map((lf, i) => {\n return (\n <div key={lf.id} className=\"flex gap-icon items-center justify-normal\">\n <span className=\"body-sm\">{resourceFormatter(lf.property)}</span>\n <form.AppField key={lf.id} name={`filters[${i}].operator`}>\n {sf => (\n <sf.TfSingleSelect\n items={FilterOperations[lf.type].map(op => ({\n id: op,\n label: <>{COMPARISON_OPERATOR_LABELS[op]}</>,\n }))}\n />\n )}\n </form.AppField>\n\n {lf.type === 'bool' && (\n <form.AppField name={`filters[${i}].value`}>\n {sf => <sf.TfCheckbox autoFocus />}\n </form.AppField>\n )}\n {lf.type === 'date' && (\n <form.AppField name={`filters[${i}].value`}>\n {_ => <TfDatePicker autoFocus />}\n </form.AppField>\n )}\n {lf.type === 'id' && (\n <form.AppField name={`filters[${i}].value`}>\n {sf => <sf.TfTextField autoFocus />}\n </form.AppField>\n )}\n {lf.type === 'string' && (\n <form.AppField name={`filters[${i}].value`}>\n {sf => <sf.TfTextField autoFocus />}\n </form.AppField>\n )}\n {lf.type === 'number' && (\n <form.AppField name={`filters[${i}].value`}>\n {sf => <sf.TfNumberField autoFocus />}\n </form.AppField>\n )}\n\n {lf.type === 'enum' && (\n <form.AppField name={`filters[${i}].value`}>\n {sf => {\n const config = filterConfig[lf.property];\n if (config.type !== 'enum') return null;\n return <sf.TfMultiSelect items={config.options} />;\n }}\n </form.AppField>\n )}\n\n {lf.type === 'id-search' && (\n <form.AppField name={`filters[${i}].value`}>\n {_ => {\n const config = filterConfig[lf.property];\n if (config.type !== 'id-search') return null;\n return (\n <TfMultipleIdSearchInput\n accessor={config.accessor}\n searchFn={config.searchFn}\n />\n );\n }}\n </form.AppField>\n )}\n\n <Button\n type=\"button\"\n variant=\"destructive\"\n size=\"icon\"\n onPress={() => field.removeValue(i)}\n >\n <IcRemove />\n </Button>\n </div>\n );\n })}\n <div className=\"flex w-full items-center justify-end gap-2 not-first:mt-icon\">\n <EasyMenu label=\"Add Filter\" autoFocus>\n {filterKeys.map(k => (\n <MenuItem\n key={k}\n onAction={() => {\n const type = filterConfig[k].type;\n const newFilter = createNewFilter(type, k);\n field.pushValue(newFilter);\n }}\n >\n {resourceFormatter(k)}\n </MenuItem>\n ))}\n </EasyMenu>\n {field.state.value.length > 0 ? (\n <Button\n type=\"button\"\n variant=\"neutral\"\n onPress={() => {\n field.setValue([]);\n }}\n >\n Reset filters\n </Button>\n ) : null}\n </div>\n </>\n );\n }}\n </form.Field>\n </form>\n </Popover>\n </PopoverTrigger>\n </section>\n );\n}\n"],"names":["getTableCallback","getter","callback","pagination","sorting","searching","filters","query","generateSortParam","_f","columnHelper","createColumnHelper","sort","cH","TABLE_CHECK_BOX_COLUMN","table","jsx","Checkbox","row","TABLE_ID_COLUMN","TABLE_DEFAULT_DATE_COLUMNS","date","formatDate","ACTIONS_COLUMN_ID","getActionColumn","rowActions","EasyMenu","IcMoreVertical","ra","MenuItem","useDataTableState","resourceName","columns","filterConfig","columnsToHideByDefault","allowSelection","initialFilters","tableActions","tableState","_setTableState","useState","rowSelection","setRowSelection","searchQuery","setSearchQuery","columnOrder","setColumnOrder","useLocalStorage","columnVisibility","setColumnVisibility","setFilters","mergedFilters","useMemo","tf","acc","current","merge","updateTableState","updates","prev","useQuery","keepPreviousData","metadataColumns","data","rowHasMetadata","rowsWithMeta","r","m","key","info","value","cols","isUpdaterFunction","updater","resolveUpdater","currentValue","tanTable","useReactTable","getCoreRowModel","useEffect","c","DataTableContext","createContext","useDataTable","ctx","useContext","DataTableProvider","children","props","DataTable","className","Fragment","classNames","Actions","jsxs","TableOverlay","Loader","IcInfo","TableContent","ColumnPicker","PageSize","Paginator","activeId","setActiveId","resourceFormatter","useResourceFormatter","sensors","useSensors","useSensor","PointerSensor","KeyboardSensor","sortableKeyboardCoordinates","DndContext","closestCenter","event","active","over","oldIndex","newIndex","arrayMove","SortableContext","verticalListSortingStrategy","IcColumns","colId","col","SortableItem","DragOverlay","column","attributes","listeners","setNodeRef","transform","transition","useSortable","style","CSS","IcGrip","SortIcon","rowCount","Button","IcFirst","IcLeft","IcRight","IcLast","PAGE_SIZES","s","items","IcRefresh","ta","i","Icon","e","DataTableFilter","SearchField","direction","IcSortAsc","IcSortDesc","IcSortNone","tableCellStyle","isSticky","TableComponent","TableHeader","headerGroup","TableRow","header","TableHead","flexRender","TableBody","cell","TableCell","FILTER_COMPARISON_OPERATORS","COMPARISON_OPERATOR_LABELS","createNewFilter","type","property","id","operator","FilterOperations","addFilterButtonRef","useRef","form","useAppForm","filterKeys","PopoverTrigger","o","IcFilter","Popover","field","lf","sf","op","_","TfDatePicker","config","TfMultipleIdSearchInput","IcRemove","k","newFilter"],"mappings":"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"}
1
+ {"version":3,"file":"data-table.js","sources":["../../lib/components/data-table.tsx","../../lib/components/data-table-filter.tsx"],"sourcesContent":["'use client';\nimport type { operations } from '@cryptlex/web-api-types/develop';\nimport {\n closestCenter,\n DndContext,\n DragOverlay,\n KeyboardSensor,\n PointerSensor,\n useSensor,\n useSensors,\n} from '@dnd-kit/core';\nimport {\n arrayMove,\n SortableContext,\n sortableKeyboardCoordinates,\n useSortable,\n verticalListSortingStrategy,\n} from '@dnd-kit/sortable';\nimport { CSS } from '@dnd-kit/utilities';\nimport { keepPreviousData, useQuery } from '@tanstack/react-query';\nimport {\n type AccessorFnColumnDef,\n type Column,\n type ColumnDef,\n type ColumnHelper,\n type ColumnOrderState,\n createColumnHelper,\n flexRender,\n getCoreRowModel,\n type PaginationState,\n type RowSelectionState,\n type SortingState,\n type Updater,\n useReactTable,\n type VisibilityState,\n} from '@tanstack/react-table';\nimport { useLocalStorage } from '@uidotdev/usehooks';\nimport { merge } from 'lodash-es';\nimport { createContext, useContext, useEffect, useMemo, useState } from 'react';\nimport type { PressEvent } from 'react-aria-components';\nimport { Button } from '../components/button';\nimport { DataTableFilter, type FiltersConfig, type TableFilter } from '../components/data-table-filter';\nimport { Loader } from '../components/loader';\nimport { EasyMenu, MenuItem } from '../components/menu';\nimport { SearchField } from '../components/searchfield';\nimport { TableBody, TableCell, Table as TableComponent, TableHead, TableHeader, TableRow } from '../components/table';\nimport { formatDate } from '../utilities/date';\nimport type { ApiSchema, CtxResourceName } from '../utilities/resources';\nimport { useResourceFormatter } from '../utilities/resources';\nimport { classNames } from '../utilities/theme';\nimport { Checkbox } from './checkbox';\nimport {\n type CtxIcon,\n IcColumns,\n IcFirst,\n IcGrip,\n IcInfo,\n IcLast,\n IcLeft,\n IcMoreVertical,\n IcRefresh,\n IcRight,\n IcSortAsc,\n IcSortDesc,\n IcSortNone,\n} from './icons';\n\n/** Reserved name for actions column */\n// export const ACTIONS_COLUMN_ID = 'tableActions';\n\nexport type TableAction<in TActionData> = {\n onClick: (e: PressEvent, t: TActionData[]) => void;\n bulk: boolean;\n icon: CtxIcon;\n tooltip?: string;\n};\n\nexport type TableFetchFn<in out TData extends object> = (\n p: PaginationState,\n s: SortingState,\n q: string,\n f: Record<string, any>\n) => Promise<{\n total: number;\n data: TData[] | undefined;\n}>;\nexport function getTableCallback<T extends object>(\n getter: (\n q: Record<string, any>\n ) => Promise<{ data?: T[]; error?: { code?: string | null; message: string }; response: Response }>\n): { callback: TableFetchFn<T>; columnHelper: ColumnHelper<T> } {\n const callback: TableFetchFn<T> = async (pagination, sorting, searching, filters) => {\n const query = {\n ...filters,\n page: pagination.pageIndex + 1,\n limit: pagination.pageSize,\n sort: generateSortParam(sorting[0]),\n search: searching,\n };\n\n const _f = await getter(query);\n\n return {\n total: Number.parseInt(_f.response.headers.get('Pagination-Count') || '0'),\n data: _f.data,\n };\n };\n\n const columnHelper = createColumnHelper<T>();\n\n return { callback, columnHelper };\n}\n\nfunction generateSortParam(sort: { id: string; desc: boolean } | undefined): string {\n if (sort) {\n if (sort.desc) {\n return `-${sort.id}`;\n } else {\n return `+${sort.id}`;\n }\n } else {\n return '-createdAt';\n }\n}\n\nconst cH = createColumnHelper<any>();\nconst TABLE_CHECK_BOX_COLUMN = [\n cH.accessor('checkbox', {\n header: ({ table }) => (\n <Checkbox\n isIndeterminate={table.getIsSomeRowsSelected() && !table.getIsAllPageRowsSelected()}\n isSelected={table.getIsAllPageRowsSelected() || table.getIsSomePageRowsSelected()}\n onChange={() => table.toggleAllPageRowsSelected()}\n aria-label=\"Select all\"\n />\n ),\n\n cell: ({ row }) => (\n <Checkbox isSelected={row.getIsSelected()} onChange={() => row.toggleSelected()} aria-label=\"Select row\" />\n ),\n enableSorting: false,\n enableHiding: false,\n }),\n];\n\nconst TABLE_ID_COLUMN = [\n cH.accessor('id', {\n header: () => 'ID',\n }),\n];\nconst TABLE_DEFAULT_DATE_COLUMNS = [\n cH.accessor('createdAt', {\n header: () => 'Creation Date',\n cell: ({ row }) => {\n const date = row.getValue('createdAt') satisfies string | null | undefined;\n return formatDate(date);\n },\n enableHiding: false,\n }),\n cH.accessor('updatedAt', {\n header: () => 'Last Updated',\n cell: ({ row }) => {\n const date = row.getValue('updatedAt') satisfies string | null | undefined;\n return formatDate(date);\n },\n enableHiding: false,\n }),\n];\n\nconst ACTIONS_COLUMN_ID = 'TableActions';\nconst getActionColumn = (rowActions: RowAction<any>[]) => {\n if (rowActions.length === 0) return [];\n\n return [\n cH.accessor(ACTIONS_COLUMN_ID, {\n header: '',\n id: ACTIONS_COLUMN_ID,\n enableHiding: false,\n cell: ({ row }) => (\n <EasyMenu label={<IcMoreVertical />} size={'icon'}>\n {rowActions.map(ra => (\n <MenuItem isDisabled={ra.disabled(row.original)} onPress={() => ra.onPress(row.original)}>\n {ra.label}\n </MenuItem>\n ))}\n </EasyMenu>\n ),\n }),\n ];\n};\n\ntype RowAction<T> = {\n onPress: (t: T) => void;\n label: React.ReactElement;\n disabled: (t: T) => boolean;\n};\n\ntype DataTableFactory<T extends object, TOperation extends keyof operations> = {\n resourceName: CtxResourceName;\n callback: TableFetchFn<T>;\n columns: ColumnDef<T, any>[];\n tableActions: TableAction<T>[];\n columnsToHideByDefault?: Partial<Record<keyof T, boolean>>; // Columns that are hidden by default\n allowSelection?: boolean;\n filterConfig: FiltersConfig<TOperation>;\n initialFilters: TableFilter[];\n rowActions?: RowAction<T>[];\n};\n\ntype DataTableState = {\n sorting: SortingState;\n pagination: PaginationState;\n};\n/**\n * Hook for handling all data-table state. Used in DataTableContext\n */\nexport function useDataTableState<T extends object, TOperation extends keyof operations>({\n resourceName,\n columns,\n callback,\n filterConfig,\n columnsToHideByDefault = {},\n allowSelection = false,\n initialFilters = [],\n tableActions,\n rowActions,\n}: DataTableFactory<T, TOperation>) {\n const [tableState, _setTableState] = useState<DataTableState>({\n /** Reflect in URL in host application */\n pagination: { pageIndex: 0, pageSize: 20 }, // Pagination state\n sorting: [], // Sorting state\n });\n //\n const [rowSelection, setRowSelection] = useState<RowSelectionState>({});\n\n /** Reflect in URL in host application */\n const [searchQuery, setSearchQuery] = useState('');\n\n const [columnOrder, setColumnOrder] = useLocalStorage<ColumnOrderState>(\n `${resourceName}_ctx_column_order_preference`,\n []\n );\n const [columnVisibility, setColumnVisibility] = useLocalStorage<VisibilityState>(\n `${resourceName}_ctx_column_visibility_preference`,\n {\n id: false,\n ...columnsToHideByDefault,\n }\n );\n\n const [filters, setFilters] = useState(initialFilters);\n\n const mergedFilters = useMemo(() => {\n // TODO, generic transform fn\n return filters\n .map(tf => {\n if (Array.isArray(tf.value)) {\n return {\n [tf.property]: {\n [tf.operator]: tf.value.join(','),\n },\n };\n }\n return {\n [tf.property]: {\n [tf.operator]: tf.value,\n },\n };\n })\n .reduce((acc, current) => {\n return merge(acc, current);\n }, {});\n }, [filters]);\n\n // Update table state with new values\n const updateTableState = (updates: Partial<DataTableState>) => {\n _setTableState(prev => ({ ...prev, ...updates }));\n };\n\n const { sorting, pagination } = tableState;\n\n const query = useQuery({\n queryKey: [resourceName, pagination, sorting, searchQuery, mergedFilters],\n queryFn: () => callback(pagination, sorting, searchQuery, mergedFilters),\n placeholderData: keepPreviousData, // Keep previous data while loading new data\n retry: 0,\n refetchOnWindowFocus: false,\n });\n\n const metadataColumns = useMemo<AccessorFnColumnDef<any, string>[]>(() => {\n const data = query.data?.data;\n if (!data?.length) return [];\n\n type WithMeta = T & { metadata: ApiSchema<'MetadataDto'>[] };\n const rowHasMetadata = (row: Record<string, any>): row is WithMeta =>\n row != null && typeof row === 'object' && 'metadata' in row && Array.isArray(row.metadata);\n\n const rowsWithMeta = data.filter(rowHasMetadata);\n if (rowsWithMeta.length === 0) return [];\n const keys: string[] = Array.from(new Set(rowsWithMeta.flatMap(r => r.metadata?.map(m => m.key) ?? [])));\n\n return keys.map(key =>\n cH.accessor(\n row => {\n if (rowHasMetadata(row)) {\n return row?.metadata?.find(m => m.key === key)?.value ?? '';\n }\n return '';\n },\n {\n id: key,\n header: key, // tooltip header\n enableSorting: false,\n cell: info => {\n const value = info.getValue();\n // Handle null/undefined values\n if (value === null || value === undefined) return '';\n // For primitive types, return the string representation\n return String(value);\n },\n }\n )\n );\n }, [query.data?.data]);\n\n /**\n * ID,createdAt and updatedAt will be added by default for all tables\n * If selection is allowed, checkbox will be added\n * If the dto has metadata, dynamics columns for all the metadata key-value will be added(particular for a view)\n * If there are actions for the table, they will be placed fixed at the right side of table.\n */\n const cols: ColumnDef<any, any>[] = [\n ...(allowSelection ? TABLE_CHECK_BOX_COLUMN : []),\n ...TABLE_ID_COLUMN,\n ...columns,\n ...(metadataColumns.length ? metadataColumns : []),\n ...TABLE_DEFAULT_DATE_COLUMNS,\n ...getActionColumn(rowActions ?? []),\n ];\n\n // Type-guard for updater\n function isUpdaterFunction<T>(updater: Updater<T>): updater is (old: T) => T {\n return typeof updater === 'function';\n }\n // Utility function to resolve updater\n function resolveUpdater<T>(updater: Updater<T>, currentValue: T) {\n if (isUpdaterFunction(updater)) {\n return updater(currentValue);\n }\n return updater;\n }\n\n // Use react-table's hook to create the table instance\n const tanTable = useReactTable({\n data: query.data?.data ?? [],\n columns: cols,\n getCoreRowModel: getCoreRowModel(),\n rowCount: query.data?.total,\n manualPagination: true, // Handle pagination manually since pagination is done server side for data tables\n onPaginationChange: updater => {\n updateTableState({ pagination: resolveUpdater(updater, pagination) });\n },\n manualSorting: true, // Handle sorting manually since sorting is done server side for data tables\n onSortingChange: updater => {\n setRowSelection({});\n updateTableState({ sorting: [...resolveUpdater(updater, sorting)] }); // Reset selection when sorting.\n },\n manualFiltering: true, // Handle filtering manually since filtering is done server side for data tables\n onColumnVisibilityChange: updater => {\n setColumnVisibility(resolveUpdater(updater, columnVisibility));\n },\n onRowSelectionChange: updater => {\n setRowSelection(resolveUpdater(updater, rowSelection));\n },\n onColumnOrderChange: updater => {\n setColumnOrder(resolveUpdater(updater, columnOrder));\n },\n state: {\n sorting: sorting,\n columnVisibility: columnVisibility,\n pagination: pagination,\n rowSelection: rowSelection,\n columnOrder: columnOrder,\n },\n meta: {\n refetch: query.refetch,\n },\n });\n\n // By default, ColumnDef does not give guarantees of column.id existing. Once useReactTable is called, all columns are assigned IDs.\n // This populates the columnIds in the columnOrder state\n useEffect(() => {\n setColumnOrder([...tanTable.getAllLeafColumns().map(c => c.id)]);\n }, []);\n\n return {\n tableState,\n updateTableState,\n query,\n setSearchQuery,\n searchQuery,\n tanTable,\n mergedFilters,\n filters,\n setFilters,\n filterConfig,\n tableActions,\n } as const;\n}\n\nexport const DataTableContext = createContext<ReturnType<typeof useDataTableState> | null>(null);\n// TODO, don't export this\nexport function useDataTable() {\n const ctx = useContext(DataTableContext);\n if (!ctx) {\n throw Error('DataTable should be used within DataTableProvider.');\n }\n return ctx;\n}\n\nexport function DataTableProvider<T extends object, TOperation extends keyof operations>({\n children,\n ...props\n}: { children: React.ReactNode } & ReturnType<typeof useDataTableState<T, TOperation>>) {\n // @ts-expect-error, propogating the generic type further will be more complex. Since this is a tightly coupled type, it should be okay but reviewed whenever useDataTableState changes.\n return <DataTableContext.Provider value={props}>{children}</DataTableContext.Provider>;\n}\n\nexport type DataTableProps = React.ComponentProps<'section'>;\nexport function DataTable({ className, ...props }: DataTableProps) {\n const { query, tanTable } = useDataTable();\n\n return (\n <>\n {/* Table Actions Section */}\n <section {...props} className={classNames('flex flex-col bg-card', className)}>\n <Actions />\n {/* The div here is necessary because TableContent is internally a <table> tag and does not respect width, height CSS */}\n <div className=\"w-full overflow-auto border-x grow min-h-table relative\" tabIndex={0}>\n {/* Table overlay with loader */}\n {query.isLoading && (\n <TableOverlay className=\"cursor-wait\">\n <Loader />\n </TableOverlay>\n )}\n {/* Table overlay for empty table */}\n {!query.isLoading && tanTable.getRowModel().rows.length === 0 && (\n // Empty table\n <TableOverlay className=\"cursor-not-allowed\">\n {!query.isFetching &&\n (query.isError ? (\n <span className=\"flex gap-3 justify-center items-center\">\n {/* TODO (mudasir-pandith) Check for 403 explicitly!! */}\n {/* <span>{query.error}</span> */}\n <IcInfo />\n <span>{query.error.message}</span>\n </span>\n ) : query.data?.data?.length === 0 ? (\n <>No results found.</>\n ) : (\n <>Unknown error. Please contact customer support.</>\n ))}\n </TableOverlay>\n )}\n {!query.isLoading && tanTable.getRowModel().rows.length !== 0 && (\n <TableContent className=\"size-full\" />\n )}\n </div>\n\n {/* Table Footer Section with Pagination and Column Picker */}\n <div className=\"flex w-full justify-between border gap-icon p-icon overflow-x-auto\">\n <div className=\"flex gap-icon\">\n <ColumnPicker />\n <PageSize />\n </div>\n <Paginator />\n </div>\n </section>\n </>\n );\n}\n/** Table overlay to be shown for loaders or other messages */\nfunction TableOverlay({ children, className }: { children: React.ReactNode; className?: string }) {\n return (\n <>\n <span\n className={classNames(\n className,\n 'absolute top-0 bg-card z-20 size-full body-sm flex items-center justify-center'\n )}\n >\n {children}\n </span>\n {/* Keep something in document flow with the correct height */}\n <span className=\"relative h-full w-0 block\" />\n </>\n );\n}\n\nfunction ColumnPicker() {\n const { tanTable } = useDataTable();\n const [activeId, setActiveId] = useState<string | null>(null);\n\n const resourceFormatter = useResourceFormatter();\n\n const sensors = useSensors(\n useSensor(PointerSensor),\n useSensor(KeyboardSensor, {\n coordinateGetter: sortableKeyboardCoordinates,\n })\n );\n return (\n <DndContext\n sensors={sensors}\n collisionDetection={closestCenter}\n onDragStart={event => {\n const { active } = event;\n setActiveId(active.id.toString());\n }}\n onDragEnd={event => {\n const { active, over } = event;\n\n if (over && active.id !== over.id) {\n const columnOrder = tanTable.getState().columnOrder;\n const oldIndex = columnOrder.indexOf(active.id.toString());\n const newIndex = columnOrder.indexOf(over.id.toString());\n tanTable.setColumnOrder([...arrayMove(columnOrder, oldIndex, newIndex)]);\n }\n\n setActiveId(null);\n }}\n >\n <SortableContext items={tanTable.getState().columnOrder} strategy={verticalListSortingStrategy}>\n <EasyMenu\n label={\n <>\n <IcColumns />\n Columns\n </>\n }\n selectionMode=\"multiple\"\n items={tanTable.getAllFlatColumns()}\n // Using selectedKeys = 'all' does not mark MenuItems with isDisabled=true as selected. This is not the intended behaviour in this use-case.\n selectedKeys={tanTable.getVisibleFlatColumns().map(c => c.id)}\n >\n <MenuItem onAction={() => tanTable.toggleAllColumnsVisible()} className={'italic'}>\n (select all)\n </MenuItem>\n {tanTable.getState().columnOrder.map(colId => {\n const col = tanTable.getAllFlatColumns().find(c => c.id === colId);\n if (!col) return null;\n return <SortableItem key={col.id} column={col} />;\n })}\n </EasyMenu>\n <DragOverlay>\n {activeId ? (\n <div className=\"opacity-70 border-2 border-primary\">{resourceFormatter(activeId)}</div>\n ) : null}\n </DragOverlay>\n </SortableContext>\n </DndContext>\n );\n\n function SortableItem({ column }: { column: Column<any, unknown> }) {\n const { attributes, listeners, setNodeRef, transform, transition } = useSortable({ id: column.id });\n const style = {\n transform: CSS.Transform.toString(transform),\n transition,\n zIndex: '999',\n };\n return (\n <MenuItem\n ref={setNodeRef}\n style={style}\n {...attributes}\n id={column.id}\n onAction={() => column.toggleVisibility()}\n isDisabled={!column.getCanHide()}\n className=\"flex items-center\"\n >\n <IcGrip {...listeners} className=\"size-icon cursor-grab\" />\n {resourceFormatter(column.id)}\n {column.getIsSorted() && <SortIcon className=\"size-icon\" direction={column.getIsSorted()} />}\n </MenuItem>\n );\n }\n}\n\nfunction Paginator() {\n const { tanTable, query } = useDataTable();\n const rowCount = query.data?.total ?? 0;\n return (\n <div className=\"flex items-center gap-2\">\n <span className=\"whitespace-nowrap body-sm text-muted\">\n {`${tanTable.getState().pagination.pageIndex * tanTable.getState().pagination.pageSize + 1} - ${Math.min(\n (tanTable.getState().pagination.pageIndex + 1) * tanTable.getState().pagination.pageSize,\n rowCount\n )} of ${rowCount?.toLocaleString()}`}\n </span>\n\n <Button\n onPress={() => tanTable.firstPage()}\n isDisabled={!tanTable.getCanPreviousPage()}\n variant=\"neutral\"\n size={'icon'}\n >\n <IcFirst />\n </Button>\n <Button\n onPress={() => tanTable.previousPage()}\n isDisabled={!tanTable.getCanPreviousPage()}\n variant=\"neutral\"\n size={'icon'}\n >\n <IcLeft />\n </Button>\n <Button\n onPress={() => tanTable.nextPage()}\n isDisabled={!tanTable.getCanNextPage()}\n variant=\"neutral\"\n size={'icon'}\n >\n <IcRight />\n </Button>\n <Button\n onClick={() => tanTable.lastPage()}\n isDisabled={!tanTable.getCanNextPage()}\n variant=\"neutral\"\n size={'icon'}\n >\n <IcLast />\n </Button>\n </div>\n );\n}\n\nfunction PageSize() {\n const { tanTable } = useDataTable();\n const PAGE_SIZES = [10, 20, 30, 40, 50];\n\n return (\n <EasyMenu\n label={tanTable.getState().pagination.pageSize.toString()}\n selectionMode=\"single\"\n selectedKeys={[tanTable.getState().pagination.pageSize.toString()]}\n items={PAGE_SIZES.map(s => ({ id: s.toString(), value: s }))}\n >\n {items => <MenuItem onAction={() => tanTable.setPageSize(items.value)}>{items.value}</MenuItem>}\n </EasyMenu>\n );\n}\n\nfunction Actions() {\n const { query, tanTable, searchQuery, setSearchQuery, tableActions } = useDataTable();\n\n return (\n <section className=\"flex bg-card justify-between my-0 p-icon border gap-icon overflow-auto\">\n <div className=\"flex gap-icon\">\n <Button isPending={query.isFetching} onClick={() => query.refetch()} variant={'neutral'} size={'icon'}>\n <IcRefresh />\n </Button>\n\n {tableActions\n .filter(ta => ta.bulk === tanTable.getSelectedRowModel().rows.length > 0)\n .map((ta, i) => {\n const Icon = ta.icon;\n return (\n <Button\n key={`${i}-${ta.bulk}`}\n type=\"button\"\n isDisabled={query.isFetching}\n className=\"animate-in fade-in slide-in-from-left-15 duration-300 transition-transform\"\n onPress={e => {\n ta.onClick(\n e,\n tanTable.getSelectedRowModel().rows.map(r => r.original)\n );\n }}\n size={'icon'}\n >\n <Icon />\n </Button>\n );\n })}\n </div>\n <div className=\"flex gap-icon\">\n <DataTableFilter />\n {<SearchField value={searchQuery} onChange={setSearchQuery} />}\n </div>\n </section>\n );\n}\n\nfunction SortIcon({\n direction,\n ...props\n}: { direction: 'asc' | 'desc' | false } & Omit<React.ComponentProps<'svg'>, 'direction'>) {\n if (direction === 'asc') return <IcSortAsc className=\"size-3.5\" {...props} />;\n else if (direction === 'desc') return <IcSortDesc className=\"size-3.5\" {...props} />;\n else return <IcSortNone className=\"size-3.5\" {...props} />;\n}\n\n// TODO, automate checking valid HTML\nfunction TableContent({ className }: React.ComponentProps<typeof TableComponent>) {\n const { tanTable } = useDataTable();\n const resourceFormatter = useResourceFormatter();\n const tableCellStyle = (isSticky: boolean, className?: string) =>\n classNames(\n 'px-icon py-2 text-left body-sm font-medium whitespace-nowrap',\n isSticky && 'bg-card sticky right-0 z-50 text-center',\n className\n );\n return (\n <TableComponent className={classNames(className)}>\n <TableHeader className=\"sticky top-0 z-10\">\n {tanTable.getHeaderGroups().map(headerGroup => (\n <TableRow key={headerGroup.id}>\n {headerGroup.headers.map(header => (\n <TableHead\n key={header.id}\n colSpan={header.colSpan}\n className={tableCellStyle(false, 'bg-card')}\n >\n {!header.column.getCanSort() &&\n !header.isPlaceholder &&\n flexRender(header.column.columnDef.header, header.getContext())}\n {header.column.getCanSort() && (\n <Button\n variant=\"ghost\"\n className=\"w-full justify-start px-1.5\"\n onPress={header.column.getToggleSortingHandler()}\n >\n <span>{resourceFormatter(header.id)}</span>\n <SortIcon direction={header.column.getIsSorted()} />\n </Button>\n )}\n </TableHead>\n ))}\n </TableRow>\n ))}\n </TableHeader>\n <TableBody className=\"flex-1 overflow-y-auto relative\">\n {tanTable.getRowModel().rows.map(row => (\n <TableRow\n className={classNames(\n 'transition-colors data-[selected=true]:bg-primary/10 hover:bg-muted-foreground/20'\n )}\n key={row.id}\n data-selected={row.getIsSelected()}\n >\n {row.getVisibleCells().map(cell => (\n <TableCell key={cell.id} className={tableCellStyle(cell.column.id === ACTIONS_COLUMN_ID)}>\n {flexRender(cell.column.columnDef.cell, cell.getContext())}\n </TableCell>\n ))}\n </TableRow>\n ))}\n </TableBody>\n </TableComponent>\n );\n}\n","'use client';\nimport type { operations } from '@cryptlex/web-api-types/develop';\nimport { useRef } from 'react';\nimport { Button } from '../components/button';\nimport { useDataTable } from '../components/data-table';\nimport { TfDatePicker } from '../components/date-picker';\nimport { EasyMenu, MenuItem } from '../components/menu';\nimport type { MultiSelectProps } from '../components/multi-select';\nimport { Popover, PopoverTrigger } from '../components/popover';\nimport { useAppForm } from '../utilities/form-hook';\nimport { useResourceFormatter, type ApiFilters } from '../utilities/resources';\nimport { classNames } from '../utilities/theme';\nimport { IcFilter, IcRemove } from './icons';\nimport { TfMultipleIdSearchInput } from './id-search';\n\nexport const FILTER_COMPARISON_OPERATORS = [\n 'eq',\n 'ne',\n 'cn',\n 'nc',\n 'sw',\n 'ew',\n 'in',\n 'nin',\n 'gt',\n 'gte',\n 'lt',\n 'lte',\n] as const;\nexport type FilterComparisonOperator = (typeof FILTER_COMPARISON_OPERATORS)[number];\n\nexport const COMPARISON_OPERATOR_LABELS: Record<FilterComparisonOperator, string> = {\n eq: 'equal to',\n ne: 'not equal to',\n cn: 'contains',\n nc: 'does not contain',\n sw: 'starts with',\n ew: 'ends with',\n in: 'includes',\n nin: 'does not include',\n gt: 'greater than',\n gte: 'greater than or equal to',\n lt: 'less than',\n lte: 'less than or equal to',\n};\n\ntype BaseLocalFilter<T extends FilterType, V> = {\n id: string;\n type: T;\n property: string;\n operator: FilterComparisonOperator;\n value: V | undefined;\n displayValue?: string;\n};\ntype EnumLocalFilter = BaseLocalFilter<'enum', Set<string | number>>;\ntype IdLocalFilter = BaseLocalFilter<'id', string>;\ntype BoolLocalFilter = BaseLocalFilter<'bool', boolean>;\ntype StringLocalFilter = BaseLocalFilter<'string', string>;\ntype NumberLocalFilter = BaseLocalFilter<'number', number>;\n// DatePicker accepts a string,and converts it to a ZonedDateTime\ntype DateLocalFilter = BaseLocalFilter<'date', string>;\ntype IdSearchLocalFilter = BaseLocalFilter<'id-search', Set<string | number>>;\n\nfunction createNewFilter(type: FilterType, property: string): TableFilter {\n const id = `${property}-${Date.now()}`;\n const operator = FilterOperations[type][0];\n\n switch (type) {\n case 'bool':\n return { id, type, property, operator, value: true };\n case 'string':\n return { id, type, property, operator, value: '' };\n case 'date':\n return { id, type, property, operator, value: new Date().toISOString() };\n case 'id':\n return { id, type, property, operator, value: '' };\n case 'id-search':\n return { id, type, property, operator, value: new Set<string | number>() };\n case 'enum':\n return { id, type, property, operator, value: new Set<string | number>() };\n case 'number':\n return { id, type, property, operator, value: 0 };\n }\n}\n\nexport type TableFilter =\n | EnumLocalFilter\n | IdLocalFilter\n | BoolLocalFilter\n | StringLocalFilter\n | DateLocalFilter\n | IdSearchLocalFilter\n | NumberLocalFilter;\n\nexport type FilterConfig =\n | { type: 'enum'; options: MultiSelectProps['items'] }\n | ({ type: 'id-search' } & Pick<React.ComponentProps<typeof TfMultipleIdSearchInput>, 'accessor' | 'searchFn'>)\n | { type: 'id' }\n | { type: 'bool' }\n | { type: 'string' }\n | { type: 'date' }\n | { type: 'number' };\n\nexport type FilterType = FilterConfig['type'];\n\nconst FilterOperations: Record<FilterType, FilterComparisonOperator[]> = {\n bool: ['eq'],\n enum: ['in', 'nin'],\n id: ['in', 'nin'],\n 'id-search': ['in', 'nin'],\n string: ['eq', 'ne', 'cn', 'nc', 'sw', 'ew', 'in', 'nin'],\n date: ['lt', 'gt'],\n number: ['eq', 'ne', 'gt', 'gte', 'lt', 'lte'],\n};\n\n// TS workaround to get rid of filterConfig: Required<Record<never, FilterConfig>>\nexport type FiltersConfig<TOperation extends keyof operations> = [keyof ApiFilters<TOperation>] extends [never]\n ? Record<string, FilterConfig>\n : Required<Record<keyof ApiFilters<TOperation>, FilterConfig>>;\n\nexport function DataTableFilter({ className, ...props }: React.ComponentProps<'section'>) {\n const { filters, query, setFilters, filterConfig } = useDataTable();\n\n const addFilterButtonRef = useRef<HTMLButtonElement>(null);\n\n const resourceFormatter = useResourceFormatter();\n\n const DEFAULT_VALUES: { filters: TableFilter[] } = {\n filters,\n };\n const form = useAppForm({\n defaultValues: DEFAULT_VALUES,\n onSubmit: ({ value }) => {\n setFilters(value.filters);\n },\n });\n\n // More reason to hate TS https://github.com/Microsoft/TypeScript/issues/12870\n const filterKeys = Object.keys(filterConfig).sort();\n\n return (\n <section {...props} className={classNames('flex gap-icon items-center', className)}>\n <PopoverTrigger\n onOpenChange={o => {\n // Set filters when the popover closes\n if (!o) {\n form.handleSubmit();\n } else {\n addFilterButtonRef.current?.focus();\n }\n }}\n >\n <div className=\"relative\">\n {filters.length > 0 && (\n <div className=\"size-2 rounded-full absolute bg-destructive z-20 top-0 right-0 translate-x-0.5 -translate-y-0.5\"></div>\n )}\n <Button\n isDisabled={query.isPending || filterKeys.length === 0}\n type=\"button\"\n size={'icon'}\n variant={'neutral'}\n >\n <IcFilter />\n </Button>\n </div>\n {/* TODO, icon maps with dynamic imports? */}\n {/* TODO open popover with form for property specific filter */}\n {/* TODO, icons here??? */}\n <Popover className=\"w-full p-icon\">\n <form\n onSubmit={e => {\n e.preventDefault();\n }}\n className=\"flex flex-col gap-icon max-h-table overflow-auto \"\n >\n <form.Field mode=\"array\" name={'filters'}>\n {field => {\n return (\n <>\n {field.state.value.map((lf, i) => {\n return (\n <div key={lf.id} className=\"flex gap-icon items-center justify-normal\">\n <span className=\"body-sm\">{resourceFormatter(lf.property)}</span>\n <form.AppField key={lf.id} name={`filters[${i}].operator`}>\n {sf => (\n <sf.TfSingleSelect\n items={FilterOperations[lf.type].map(op => ({\n id: op,\n label: <>{COMPARISON_OPERATOR_LABELS[op]}</>,\n }))}\n />\n )}\n </form.AppField>\n\n {lf.type === 'bool' && (\n <form.AppField name={`filters[${i}].value`}>\n {sf => <sf.TfCheckbox autoFocus />}\n </form.AppField>\n )}\n {lf.type === 'date' && (\n <form.AppField name={`filters[${i}].value`}>\n {_ => <TfDatePicker autoFocus />}\n </form.AppField>\n )}\n {lf.type === 'id' && (\n <form.AppField name={`filters[${i}].value`}>\n {sf => <sf.TfTextField autoFocus />}\n </form.AppField>\n )}\n {lf.type === 'string' && (\n <form.AppField name={`filters[${i}].value`}>\n {sf => <sf.TfTextField autoFocus />}\n </form.AppField>\n )}\n {lf.type === 'number' && (\n <form.AppField name={`filters[${i}].value`}>\n {sf => <sf.TfNumberField autoFocus />}\n </form.AppField>\n )}\n\n {lf.type === 'enum' && (\n <form.AppField name={`filters[${i}].value`}>\n {sf => {\n const config = filterConfig[lf.property];\n if (config.type !== 'enum') return null;\n return <sf.TfMultiSelect items={config.options} />;\n }}\n </form.AppField>\n )}\n\n {lf.type === 'id-search' && (\n <form.AppField name={`filters[${i}].value`}>\n {_ => {\n const config = filterConfig[lf.property];\n if (config.type !== 'id-search') return null;\n return (\n <TfMultipleIdSearchInput\n accessor={config.accessor}\n searchFn={config.searchFn}\n />\n );\n }}\n </form.AppField>\n )}\n\n <Button\n type=\"button\"\n variant=\"destructive\"\n size=\"icon\"\n onPress={() => field.removeValue(i)}\n >\n <IcRemove />\n </Button>\n </div>\n );\n })}\n <div className=\"flex w-full items-center justify-end gap-2 not-first:mt-icon\">\n <EasyMenu label=\"Add Filter\" autoFocus>\n {filterKeys.map(k => (\n <MenuItem\n key={k}\n onAction={() => {\n const type = filterConfig[k].type;\n const newFilter = createNewFilter(type, k);\n field.pushValue(newFilter);\n }}\n >\n {resourceFormatter(k)}\n </MenuItem>\n ))}\n </EasyMenu>\n {field.state.value.length > 0 ? (\n <Button\n type=\"button\"\n variant=\"neutral\"\n onPress={() => {\n field.setValue([]);\n }}\n >\n Reset filters\n </Button>\n ) : null}\n </div>\n </>\n );\n }}\n </form.Field>\n </form>\n </Popover>\n </PopoverTrigger>\n </section>\n );\n}\n"],"names":["getTableCallback","getter","callback","pagination","sorting","searching","filters","query","generateSortParam","_f","columnHelper","createColumnHelper","sort","cH","TABLE_CHECK_BOX_COLUMN","table","jsx","Checkbox","row","TABLE_ID_COLUMN","TABLE_DEFAULT_DATE_COLUMNS","date","formatDate","ACTIONS_COLUMN_ID","getActionColumn","rowActions","EasyMenu","IcMoreVertical","ra","MenuItem","useDataTableState","resourceName","columns","filterConfig","columnsToHideByDefault","allowSelection","initialFilters","tableActions","tableState","_setTableState","useState","rowSelection","setRowSelection","searchQuery","setSearchQuery","columnOrder","setColumnOrder","useLocalStorage","columnVisibility","setColumnVisibility","setFilters","mergedFilters","useMemo","tf","acc","current","merge","updateTableState","updates","prev","useQuery","keepPreviousData","metadataColumns","data","rowHasMetadata","rowsWithMeta","r","m","key","info","value","cols","isUpdaterFunction","updater","resolveUpdater","currentValue","tanTable","useReactTable","getCoreRowModel","useEffect","c","DataTableContext","createContext","useDataTable","ctx","useContext","DataTableProvider","children","props","DataTable","className","Fragment","classNames","Actions","jsxs","TableOverlay","Loader","IcInfo","TableContent","ColumnPicker","PageSize","Paginator","activeId","setActiveId","resourceFormatter","useResourceFormatter","sensors","useSensors","useSensor","PointerSensor","KeyboardSensor","sortableKeyboardCoordinates","DndContext","closestCenter","event","active","over","oldIndex","newIndex","arrayMove","SortableContext","verticalListSortingStrategy","IcColumns","colId","col","SortableItem","DragOverlay","column","attributes","listeners","setNodeRef","transform","transition","useSortable","style","CSS","IcGrip","SortIcon","rowCount","Button","IcFirst","IcLeft","IcRight","IcLast","PAGE_SIZES","s","items","IcRefresh","ta","i","Icon","e","DataTableFilter","SearchField","direction","IcSortAsc","IcSortDesc","IcSortNone","tableCellStyle","isSticky","TableComponent","TableHeader","headerGroup","TableRow","header","TableHead","flexRender","TableBody","cell","TableCell","FILTER_COMPARISON_OPERATORS","COMPARISON_OPERATOR_LABELS","createNewFilter","type","property","id","operator","FilterOperations","addFilterButtonRef","useRef","form","useAppForm","filterKeys","PopoverTrigger","o","IcFilter","Popover","field","lf","sf","op","_","TfDatePicker","config","TfMultipleIdSearchInput","IcRemove","k","newFilter"],"mappings":"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"}
@@ -1,2 +1,2 @@
1
- import{jsxs as i,jsx as e}from"react/jsx-runtime";import{DatePicker as x,composeRenderProps as c,DateRangePicker as v,Popover as D,Dialog as N}from"react-aria-components";import{parseAbsolute as P,getLocalTimeZone as k}from"@internationalized/date";import{Button as p}from"./button.js";import{Calendar as C,RangeCalendar as b}from"./calendar.js";import{DateInput as m}from"./datefield.js";import{FormField as u,FieldGroup as f}from"./field.js";import{getFieldErrorMessage as d}from"../utilities/form.js";import{useFieldContext as F}from"../utilities/form-context.js";import{classNames as n}from"../utilities/theme.js";import{IcDate as g}from"./icons.js";import"class-variance-authority";import"./loader.js";import"react";import"@tanstack/react-form";import"clsx";const h=({className:a,popoverClassName:r,...o})=>e(D,{className:c(r,t=>n("w-auto p-3 bg-popover border",t)),children:e(N,{className:n("flex w-full flex-col gap-y-2 outline-none sm:flex-row sm:gap-x-icon sm:gap-y-0",a),...o})});function R({label:a,description:r,errorMessage:o,className:t,...l}){return i(x,{className:c(t,s=>n("group flex flex-col gap-2",s)),...l,children:[e(u,{label:a,description:r,errorMessage:o,children:i(f,{"aria-label":a,children:[e(m,{className:"flex-1",variant:"ghost"}),e(p,{variant:"ghost",size:"icon",className:"-me-2 ms-2",children:e(g,{"aria-hidden":!0})})]})}),e(h,{children:e(C,{})})]})}function H({...a}){const r=F();return e(R,{hideTimeZone:!0,value:r.state.value?P(r.state.value,k()):null,onChange:o=>o?r.handleChange(o.toAbsoluteString()):r.handleChange(null),onBlur:r.handleBlur,isInvalid:!!d(r),errorMessage:d(r),...a})}function J({label:a,description:r,errorMessage:o,className:t,...l}){return i(v,{className:c(t,s=>n("group flex flex-col gap-2",s)),...l,children:[e(u,{label:a,errorMessage:o,description:r,children:i(f,{children:[e(m,{variant:"ghost",slot:"start"}),e("span",{"aria-hidden":!0,className:"px-2 body-sm text-muted-foreground",children:"-"}),e(m,{className:"flex-1",variant:"ghost",slot:"end"}),e(p,{variant:"ghost",size:"icon",className:"mr-1 data-[focus-visible]:ring-offset-0",children:e(g,{"aria-hidden":!0})})]})}),e(h,{children:e(b,{})})]})}export{R as DatePicker,J as DateRangePicker,H as TfDatePicker};
1
+ import{jsxs as o,jsx as e}from"react/jsx-runtime";import{DatePicker as x,composeRenderProps as c,DateRangePicker as D,Popover as b,Dialog as v}from"react-aria-components";import{parseAbsolute as N,getLocalTimeZone as P}from"@internationalized/date";import{Button as u}from"./button.js";import{Calendar as k,RangeCalendar as C}from"./calendar.js";import{DateInput as m}from"./datefield.js";import{FormField as f,FieldGroup as p}from"./field.js";import{getFieldErrorMessage as d}from"../utilities/form.js";import{useFieldContext as F}from"../utilities/form-context.js";import{classNames as l}from"../utilities/theme.js";import{IcDate as g}from"./icons.js";import"class-variance-authority";import"./loader.js";import"react";import"@tanstack/react-form";import"clsx";const h=({className:a,popoverClassName:r,...i})=>e(b,{className:c(r,t=>l("w-auto p-3 bg-popover border",t)),children:e(v,{className:l("flex w-full flex-col gap-y-2 outline-none sm:flex-row sm:gap-x-icon sm:gap-y-0",a),...i})});function R({label:a,description:r,errorMessage:i,className:t,...n}){return o(x,{className:c(t,s=>l("group flex flex-col gap-2",s)),...n,children:[e(f,{label:a,description:r,errorMessage:i,children:o(p,{"aria-label":a,children:[e(m,{className:"flex-1",variant:"ghost"}),e(u,{variant:"ghost",size:"icon",className:"-me-2 ms-2",children:e(g,{"aria-hidden":!0})})]})}),e(h,{children:e(k,{})})]})}function H({...a}){const r=F({disabled:a.isDisabled});return e(R,{hideTimeZone:!0,isDisabled:a.isDisabled||r.form.state.isSubmitting,value:r.state.value?N(r.state.value,P()):null,onChange:i=>i?r.handleChange(i.toAbsoluteString()):r.handleChange(null),onBlur:r.handleBlur,isInvalid:!!d(r),errorMessage:d(r),...a})}function J({label:a,description:r,errorMessage:i,className:t,...n}){return o(D,{className:c(t,s=>l("group flex flex-col gap-2",s)),...n,children:[e(f,{label:a,errorMessage:i,description:r,children:o(p,{children:[e(m,{variant:"ghost",slot:"start"}),e("span",{"aria-hidden":!0,className:"px-2 body-sm text-muted-foreground",children:"-"}),e(m,{className:"flex-1",variant:"ghost",slot:"end"}),e(u,{variant:"ghost",size:"icon",className:"mr-1 data-[focus-visible]:ring-offset-0",children:e(g,{"aria-hidden":!0})})]})}),e(h,{children:e(C,{})})]})}export{R as DatePicker,J as DateRangePicker,H as TfDatePicker};
2
2
  //# sourceMappingURL=date-picker.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"date-picker.js","sources":["../../lib/components/date-picker.tsx"],"sourcesContent":["import {\n DatePicker as AriaDatePicker,\n DatePickerProps as AriaDatePickerProps,\n DateRangePicker as AriaDateRangePicker,\n DateRangePickerProps as AriaDateRangePickerProps,\n DateValue as AriaDateValue,\n Dialog as AriaDialog,\n DialogProps as AriaDialogProps,\n PopoverProps as AriaPopoverProps,\n composeRenderProps,\n Popover,\n} from 'react-aria-components';\n\nimport { getLocalTimeZone, parseAbsolute, type ZonedDateTime } from '@internationalized/date';\nimport { Button } from '../components/button';\nimport { Calendar, RangeCalendar } from '../components/calendar';\nimport { DateInput } from '../components/datefield';\nimport { FieldGroup, FormField, type FormFieldProps } from '../components/field';\nimport { getFieldErrorMessage } from '../utilities/form';\nimport { useFieldContext } from '../utilities/form-context';\nimport { classNames } from '../utilities/theme';\nimport { IcDate } from './icons';\n\nconst DatePickerContent = ({\n className,\n popoverClassName,\n ...props\n}: AriaDialogProps & { popoverClassName?: AriaPopoverProps['className'] }) => (\n <Popover\n className={composeRenderProps(popoverClassName, className =>\n classNames('w-auto p-3 bg-popover border', className)\n )}\n >\n <AriaDialog\n className={classNames(\n 'flex w-full flex-col gap-y-2 outline-none sm:flex-row sm:gap-x-icon sm:gap-y-0',\n className\n )}\n {...props}\n />\n </Popover>\n);\n\ninterface DatePickerProps<T extends AriaDateValue> extends AriaDatePickerProps<T>, FormFieldProps {}\n\nexport function DatePicker<T extends AriaDateValue>({\n label,\n description,\n errorMessage,\n className,\n ...props\n}: DatePickerProps<T>) {\n return (\n <AriaDatePicker\n className={composeRenderProps(className, className => classNames('group flex flex-col gap-2', className))}\n {...props}\n >\n <FormField label={label} description={description} errorMessage={errorMessage}>\n <FieldGroup aria-label={label}>\n <DateInput className=\"flex-1\" variant=\"ghost\" />\n <Button variant=\"ghost\" size=\"icon\" className={'-me-2 ms-2'}>\n <IcDate aria-hidden />\n </Button>\n </FieldGroup>\n </FormField>\n <DatePickerContent>\n <Calendar />\n </DatePickerContent>\n </AriaDatePicker>\n );\n}\n\nexport function TfDatePicker({\n ...props\n}: Omit<DatePickerProps<ZonedDateTime>, 'value' | 'onChange' | 'onBlur' | 'isInvalid' | 'errorMessage'>) {\n const field = useFieldContext<string | null>();\n return (\n <DatePicker\n hideTimeZone\n value={field.state.value ? parseAbsolute(field.state.value, getLocalTimeZone()) : null}\n onChange={v => (v ? field.handleChange(v.toAbsoluteString()) : field.handleChange(null))}\n onBlur={field.handleBlur}\n isInvalid={!!getFieldErrorMessage(field)}\n errorMessage={getFieldErrorMessage(field)}\n {...props}\n />\n );\n}\n\ninterface DateRangePickerProps<T extends AriaDateValue> extends AriaDateRangePickerProps<T>, FormFieldProps {}\nexport function DateRangePicker<T extends AriaDateValue>({\n label,\n description,\n errorMessage,\n className,\n ...props\n}: DateRangePickerProps<T>) {\n return (\n <AriaDateRangePicker\n className={composeRenderProps(className, className => classNames('group flex flex-col gap-2', className))}\n {...props}\n >\n <FormField label={label} errorMessage={errorMessage} description={description}>\n <FieldGroup>\n <DateInput variant=\"ghost\" slot={'start'} />\n <span aria-hidden className=\"px-2 body-sm text-muted-foreground\">\n -\n </span>\n <DateInput className=\"flex-1\" variant=\"ghost\" slot={'end'} />\n <Button variant=\"ghost\" size=\"icon\" className=\"mr-1 data-[focus-visible]:ring-offset-0\">\n <IcDate aria-hidden />\n </Button>\n </FieldGroup>\n </FormField>\n <DatePickerContent>\n <RangeCalendar />\n </DatePickerContent>\n </AriaDateRangePicker>\n );\n}\n"],"names":["DatePickerContent","className","popoverClassName","props","jsx","Popover","composeRenderProps","classNames","AriaDialog","DatePicker","label","description","errorMessage","jsxs","AriaDatePicker","FormField","FieldGroup","DateInput","Button","IcDate","Calendar","TfDatePicker","field","useFieldContext","parseAbsolute","getLocalTimeZone","v","getFieldErrorMessage","DateRangePicker","AriaDateRangePicker","RangeCalendar"],"mappings":"2vBAuBA,MAAMA,EAAoB,CAAC,CACvB,UAAAC,EACA,iBAAAC,EACA,GAAGC,CACP,IACIC,EAACC,EAAA,CACG,UAAWC,EAAmBJ,EAAkBD,GAC5CM,EAAW,+BAAgCN,CAAS,CAAA,EAGxD,SAAAG,EAACI,EAAA,CACG,UAAWD,EACP,iFACAN,CAAA,EAEH,GAAGE,CAAA,CAAA,CACR,CACJ,EAKG,SAASM,EAAoC,CAChD,MAAAC,EACA,YAAAC,EACA,aAAAC,EACA,UAAAX,EACA,GAAGE,CACP,EAAuB,CACnB,OACIU,EAACC,EAAA,CACG,UAAWR,EAAmBL,EAAWA,GAAaM,EAAW,4BAA6BN,CAAS,CAAC,EACvG,GAAGE,EAEJ,SAAA,CAAAC,EAACW,GAAU,MAAAL,EAAc,YAAAC,EAA0B,aAAAC,EAC/C,SAAAC,EAACG,EAAA,CAAW,aAAYN,EACpB,SAAA,CAAAN,EAACa,EAAA,CAAU,UAAU,SAAS,QAAQ,QAAQ,EAC9Cb,EAACc,EAAA,CAAO,QAAQ,QAAQ,KAAK,OAAO,UAAW,aAC3C,SAAAd,EAACe,EAAA,CAAO,cAAW,EAAA,CAAC,CAAA,CACxB,CAAA,CAAA,CACJ,CAAA,CACJ,EACAf,EAACJ,EAAA,CACG,SAAAI,EAACgB,EAAA,CAAA,CAAS,CAAA,CACd,CAAA,CAAA,CAAA,CAGZ,CAEO,SAASC,EAAa,CACzB,GAAGlB,CACP,EAAyG,CACrG,MAAMmB,EAAQC,EAAA,EACd,OACInB,EAACK,EAAA,CACG,aAAY,GACZ,MAAOa,EAAM,MAAM,MAAQE,EAAcF,EAAM,MAAM,MAAOG,EAAA,CAAkB,EAAI,KAClF,SAAUC,GAAMA,EAAIJ,EAAM,aAAaI,EAAE,kBAAkB,EAAIJ,EAAM,aAAa,IAAI,EACtF,OAAQA,EAAM,WACd,UAAW,CAAC,CAACK,EAAqBL,CAAK,EACvC,aAAcK,EAAqBL,CAAK,EACvC,GAAGnB,CAAA,CAAA,CAGhB,CAGO,SAASyB,EAAyC,CACrD,MAAAlB,EACA,YAAAC,EACA,aAAAC,EACA,UAAAX,EACA,GAAGE,CACP,EAA4B,CACxB,OACIU,EAACgB,EAAA,CACG,UAAWvB,EAAmBL,EAAWA,GAAaM,EAAW,4BAA6BN,CAAS,CAAC,EACvG,GAAGE,EAEJ,SAAA,CAAAC,EAACW,EAAA,CAAU,MAAAL,EAAc,aAAAE,EAA4B,YAAAD,EACjD,WAACK,EAAA,CACG,SAAA,CAAAZ,EAACa,EAAA,CAAU,QAAQ,QAAQ,KAAM,QAAS,IACzC,OAAA,CAAK,cAAW,GAAC,UAAU,qCAAqC,SAAA,IAEjE,IACCA,EAAA,CAAU,UAAU,SAAS,QAAQ,QAAQ,KAAM,MAAO,EAC3Db,EAACc,EAAA,CAAO,QAAQ,QAAQ,KAAK,OAAO,UAAU,0CAC1C,SAAAd,EAACe,EAAA,CAAO,cAAW,EAAA,CAAC,CAAA,CACxB,CAAA,CAAA,CACJ,CAAA,CACJ,EACAf,EAACJ,EAAA,CACG,SAAAI,EAAC0B,EAAA,CAAA,CAAc,CAAA,CACnB,CAAA,CAAA,CAAA,CAGZ"}
1
+ {"version":3,"file":"date-picker.js","sources":["../../lib/components/date-picker.tsx"],"sourcesContent":["import {\n DatePicker as AriaDatePicker,\n DatePickerProps as AriaDatePickerProps,\n DateRangePicker as AriaDateRangePicker,\n DateRangePickerProps as AriaDateRangePickerProps,\n DateValue as AriaDateValue,\n Dialog as AriaDialog,\n DialogProps as AriaDialogProps,\n PopoverProps as AriaPopoverProps,\n composeRenderProps,\n Popover,\n} from 'react-aria-components';\n\nimport { getLocalTimeZone, parseAbsolute, type ZonedDateTime } from '@internationalized/date';\nimport { Button } from '../components/button';\nimport { Calendar, RangeCalendar } from '../components/calendar';\nimport { DateInput } from '../components/datefield';\nimport { FieldGroup, FormField, type FormFieldProps } from '../components/field';\nimport { getFieldErrorMessage } from '../utilities/form';\nimport { useFieldContext } from '../utilities/form-context';\nimport { classNames } from '../utilities/theme';\nimport { IcDate } from './icons';\n\nconst DatePickerContent = ({\n className,\n popoverClassName,\n ...props\n}: AriaDialogProps & { popoverClassName?: AriaPopoverProps['className'] }) => (\n <Popover\n className={composeRenderProps(popoverClassName, className =>\n classNames('w-auto p-3 bg-popover border', className)\n )}\n >\n <AriaDialog\n className={classNames(\n 'flex w-full flex-col gap-y-2 outline-none sm:flex-row sm:gap-x-icon sm:gap-y-0',\n className\n )}\n {...props}\n />\n </Popover>\n);\n\ninterface DatePickerProps<T extends AriaDateValue> extends AriaDatePickerProps<T>, FormFieldProps {}\n\nexport function DatePicker<T extends AriaDateValue>({\n label,\n description,\n errorMessage,\n className,\n ...props\n}: DatePickerProps<T>) {\n return (\n <AriaDatePicker\n className={composeRenderProps(className, className => classNames('group flex flex-col gap-2', className))}\n {...props}\n >\n <FormField label={label} description={description} errorMessage={errorMessage}>\n <FieldGroup aria-label={label}>\n <DateInput className=\"flex-1\" variant=\"ghost\" />\n <Button variant=\"ghost\" size=\"icon\" className={'-me-2 ms-2'}>\n <IcDate aria-hidden />\n </Button>\n </FieldGroup>\n </FormField>\n <DatePickerContent>\n <Calendar />\n </DatePickerContent>\n </AriaDatePicker>\n );\n}\n\nexport function TfDatePicker({\n ...props\n}: Omit<DatePickerProps<ZonedDateTime>, 'value' | 'onChange' | 'onBlur' | 'isInvalid' | 'errorMessage'>) {\n const field = useFieldContext<string | null>({ disabled: props.isDisabled });\n return (\n <DatePicker\n hideTimeZone\n isDisabled={props.isDisabled || field.form.state.isSubmitting}\n value={field.state.value ? parseAbsolute(field.state.value, getLocalTimeZone()) : null}\n onChange={v => (v ? field.handleChange(v.toAbsoluteString()) : field.handleChange(null))}\n onBlur={field.handleBlur}\n isInvalid={!!getFieldErrorMessage(field)}\n errorMessage={getFieldErrorMessage(field)}\n {...props}\n />\n );\n}\n\ninterface DateRangePickerProps<T extends AriaDateValue> extends AriaDateRangePickerProps<T>, FormFieldProps {}\nexport function DateRangePicker<T extends AriaDateValue>({\n label,\n description,\n errorMessage,\n className,\n ...props\n}: DateRangePickerProps<T>) {\n return (\n <AriaDateRangePicker\n className={composeRenderProps(className, className => classNames('group flex flex-col gap-2', className))}\n {...props}\n >\n <FormField label={label} errorMessage={errorMessage} description={description}>\n <FieldGroup>\n <DateInput variant=\"ghost\" slot={'start'} />\n <span aria-hidden className=\"px-2 body-sm text-muted-foreground\">\n -\n </span>\n <DateInput className=\"flex-1\" variant=\"ghost\" slot={'end'} />\n <Button variant=\"ghost\" size=\"icon\" className=\"mr-1 data-[focus-visible]:ring-offset-0\">\n <IcDate aria-hidden />\n </Button>\n </FieldGroup>\n </FormField>\n <DatePickerContent>\n <RangeCalendar />\n </DatePickerContent>\n </AriaDateRangePicker>\n );\n}\n"],"names":["DatePickerContent","className","popoverClassName","props","jsx","Popover","composeRenderProps","classNames","AriaDialog","DatePicker","label","description","errorMessage","jsxs","AriaDatePicker","FormField","FieldGroup","DateInput","Button","IcDate","Calendar","TfDatePicker","field","useFieldContext","parseAbsolute","getLocalTimeZone","v","getFieldErrorMessage","DateRangePicker","AriaDateRangePicker","RangeCalendar"],"mappings":"2vBAuBA,MAAMA,EAAoB,CAAC,CACvB,UAAAC,EACA,iBAAAC,EACA,GAAGC,CACP,IACIC,EAACC,EAAA,CACG,UAAWC,EAAmBJ,EAAkBD,GAC5CM,EAAW,+BAAgCN,CAAS,CAAA,EAGxD,SAAAG,EAACI,EAAA,CACG,UAAWD,EACP,iFACAN,CAAA,EAEH,GAAGE,CAAA,CAAA,CACR,CACJ,EAKG,SAASM,EAAoC,CAChD,MAAAC,EACA,YAAAC,EACA,aAAAC,EACA,UAAAX,EACA,GAAGE,CACP,EAAuB,CACnB,OACIU,EAACC,EAAA,CACG,UAAWR,EAAmBL,EAAWA,GAAaM,EAAW,4BAA6BN,CAAS,CAAC,EACvG,GAAGE,EAEJ,SAAA,CAAAC,EAACW,GAAU,MAAAL,EAAc,YAAAC,EAA0B,aAAAC,EAC/C,SAAAC,EAACG,EAAA,CAAW,aAAYN,EACpB,SAAA,CAAAN,EAACa,EAAA,CAAU,UAAU,SAAS,QAAQ,QAAQ,EAC9Cb,EAACc,EAAA,CAAO,QAAQ,QAAQ,KAAK,OAAO,UAAW,aAC3C,SAAAd,EAACe,EAAA,CAAO,cAAW,EAAA,CAAC,CAAA,CACxB,CAAA,CAAA,CACJ,CAAA,CACJ,EACAf,EAACJ,EAAA,CACG,SAAAI,EAACgB,EAAA,CAAA,CAAS,CAAA,CACd,CAAA,CAAA,CAAA,CAGZ,CAEO,SAASC,EAAa,CACzB,GAAGlB,CACP,EAAyG,CACrG,MAAMmB,EAAQC,EAA+B,CAAE,SAAUpB,EAAM,WAAY,EAC3E,OACIC,EAACK,EAAA,CACG,aAAY,GACZ,WAAYN,EAAM,YAAcmB,EAAM,KAAK,MAAM,aACjD,MAAOA,EAAM,MAAM,MAAQE,EAAcF,EAAM,MAAM,MAAOG,EAAA,CAAkB,EAAI,KAClF,SAAUC,GAAMA,EAAIJ,EAAM,aAAaI,EAAE,kBAAkB,EAAIJ,EAAM,aAAa,IAAI,EACtF,OAAQA,EAAM,WACd,UAAW,CAAC,CAACK,EAAqBL,CAAK,EACvC,aAAcK,EAAqBL,CAAK,EACvC,GAAGnB,CAAA,CAAA,CAGhB,CAGO,SAASyB,EAAyC,CACrD,MAAAlB,EACA,YAAAC,EACA,aAAAC,EACA,UAAAX,EACA,GAAGE,CACP,EAA4B,CACxB,OACIU,EAACgB,EAAA,CACG,UAAWvB,EAAmBL,EAAWA,GAAaM,EAAW,4BAA6BN,CAAS,CAAC,EACvG,GAAGE,EAEJ,SAAA,CAAAC,EAACW,EAAA,CAAU,MAAAL,EAAc,aAAAE,EAA4B,YAAAD,EACjD,WAACK,EAAA,CACG,SAAA,CAAAZ,EAACa,EAAA,CAAU,QAAQ,QAAQ,KAAM,QAAS,IACzC,OAAA,CAAK,cAAW,GAAC,UAAU,qCAAqC,SAAA,IAEjE,IACCA,EAAA,CAAU,UAAU,SAAS,QAAQ,QAAQ,KAAM,MAAO,EAC3Db,EAACc,EAAA,CAAO,QAAQ,QAAQ,KAAK,OAAO,UAAU,0CAC1C,SAAAd,EAACe,EAAA,CAAO,cAAW,EAAA,CAAC,CAAA,CACxB,CAAA,CAAA,CACJ,CAAA,CACJ,EACAf,EAACJ,EAAA,CACG,SAAAI,EAAC0B,EAAA,CAAA,CAAc,CAAA,CACnB,CAAA,CAAA,CAAA,CAGZ"}
@@ -1,20 +1,129 @@
1
1
  import { Menu } from '../components/menu';
2
2
  import { FormFieldProps } from './field';
3
+ /**
4
+ * Minimal resource shape used by the ID search inputs.
5
+ * Only `id` and `name` are required.
6
+ *
7
+ * @example
8
+ * const user: BaseSearchableResource = { id: 'u_123', name: 'Nabeel Farooq' };
9
+ */
3
10
  type BaseSearchableResource = {
11
+ /** Unique identifier used as the input value. */
4
12
  id: string;
13
+ /** Human-readable label shown to users. */
5
14
  name: string;
6
15
  };
16
+ /**
17
+ * - Generic, accessible ID-search building block.
18
+ * - Search (powered by react-query)
19
+ * - Renders an accessible Autocomplete + Menu listbox
20
+ * - Exposes a controlled `value`/`onChange` contract so callers (and wrappers) can manage state
21
+ * - Clear separation of concerns: this component only handles UI search/display; callers provide `searchFn`
22
+ *
23
+ * @template T - resource type extending `BaseSearchableResource` (must have `id` and `name`)
24
+ * @template V - controlled value type (e.g. `string` for single-select or `string[]` for multi-select)
25
+ *
26
+ * @param props - props object (see inline property JSDoc for the most important fields)
27
+ *
28
+ * @remarks
29
+ * - `searchFn` should return `Promise<T[] | undefined>`. Returning `undefined` indicates no results / handled error.
30
+ * - When the popover closes, `onBlur` (if provided) is called with the current `value`.
31
+ * - `renderLabel` must convert `value` to a readable string for the control button.
32
+ *
33
+ * @example
34
+ * <BaseIdSearchInput
35
+ * label="Owner"
36
+ * searchFn={q => api.searchUsers(q)}
37
+ * value={ownerId}
38
+ * onChange={setOwnerId}
39
+ * renderLabel={(v, data) => data?.find(d => d.id === v)?.name ?? v}
40
+ * />
41
+ *
42
+ * @testing
43
+ * - Mock `searchFn` in unit tests; assert keyboard navigation, open/close behavior, and `onBlur` call on popover close.
44
+ */
7
45
  declare function BaseIdSearchInput<T extends BaseSearchableResource, V>({ label, description, errorMessage, searchFn, isDisabled, onBlur, onChange, value, renderLabel, ...props }: FormFieldProps & {
46
+ /** Function that returns matching resources for the current query. */
8
47
  searchFn: (q: string) => Promise<T[] | undefined>;
48
+ /** Disable interactions. */
9
49
  isDisabled?: boolean;
50
+ /** Key used to access an alternate display accessor on item (kept for compatibility). */
10
51
  accessor: keyof BaseSearchableResource;
52
+ /** Controlled value. */
11
53
  value: V;
54
+ /** Called when popover closes or the field blurs with the current value. */
12
55
  onBlur?: (v: V) => void;
56
+ /** Controlled change handler. */
13
57
  onChange: (v: V) => void;
58
+ /** Render a human-readable label for the current value using the latest data. */
14
59
  renderLabel: (v: V, data: T[] | undefined) => string;
15
60
  } & Omit<React.ComponentProps<typeof Menu>, 'items' | 'className'>): import("react/jsx-runtime").JSX.Element;
61
+ /**
62
+ * Single-selection ID search input.
63
+ *
64
+ * Thin, typed wrapper around `BaseIdSearchInput` specialized for the very common single-ID case.
65
+ * Adapts the internal selection events into `onChange(id?: string)` and renders the selected label.
66
+ *
67
+ * @template T - resource type (extends BaseSearchableResource)
68
+ *
69
+ * @param props - Inherits `BaseIdSearchInput` props but uses `string[]` value type.
70
+ *
71
+ * @example
72
+ * <SingleIdSearchInput
73
+ * label="Reporter"
74
+ * value={reporterId}
75
+ * onChange={setReporterId}
76
+ * searchFn={q => api.searchUsers(q)}
77
+ * />
78
+ *
79
+ */
16
80
  export declare function SingleIdSearchInput<T extends BaseSearchableResource>({ ...props }: Omit<React.ComponentProps<typeof BaseIdSearchInput<T, string>>, 'onSelectionChange' | 'selectionMode' | 'selectedKeys' | 'renderLabel'>): import("react/jsx-runtime").JSX.Element;
81
+ /**
82
+ * Multi-selection ID search input.
83
+ *
84
+ * Thin wrapper around `BaseIdSearchInput` for the multiple-ID (`string[]`) case.
85
+ * Adapts internal selection events into `onChange(ids: string[])`.
86
+ *
87
+ * @template T - resource type (extends BaseSearchableResource)
88
+ *
89
+ * @param props - Inherits `BaseIdSearchInput` props but uses `string[]` value type.
90
+ *
91
+ * @example
92
+ * <MultipleIdSearchInput
93
+ * label="Reviewers"
94
+ * value={reviewerIds}
95
+ * onChange={setReviewerIds}
96
+ * searchFn={q => api.searchUsers(q)}
97
+ * />
98
+ *
99
+ * @remarks
100
+ * - The `renderLabel` joins selected item names with commas for compact display.
101
+ */
17
102
  export declare function MultipleIdSearchInput<T extends BaseSearchableResource>({ ...props }: Omit<React.ComponentProps<typeof BaseIdSearchInput<T, string[]>>, 'renderLabel' | 'onSelectionChange' | 'selectionMode' | 'selectedKeys'>): import("react/jsx-runtime").JSX.Element;
103
+ /**
104
+ * Form-integrated single-select ID input (field wrapper).
105
+ *
106
+ * Integrates `SingleIdSearchInput` into the form system using `useFieldContext`.
107
+ * - wires `value`, `onChange`, and `onBlur`
108
+ * - disables the control while the form is submitting
109
+ * - surfaces field-level error messages
110
+ *
111
+ * @example
112
+ * <TfSingleIdSearchInput name="ownerId" label="Owner" searchFn={q => api.searchUsers(q)} />
113
+
114
+ */
18
115
  export declare function TfSingleIdSearchInput({ isDisabled, ...props }: Omit<React.ComponentProps<typeof SingleIdSearchInput>, 'value' | 'onChange'>): import("react/jsx-runtime").JSX.Element;
116
+ /**
117
+ * Form-integrated multi-select ID input (field wrapper).
118
+ *
119
+ * Integrates `MultipleIdSearchInput` into the form system using `useFieldContext`.
120
+ * - wires `value`, `onChange`, and `onBlur`
121
+ * - disables the control while the form is submitting
122
+ * - surfaces field-level error messages
123
+ *
124
+ * @example
125
+ * <TfMultipleIdSearchInput name="reviewerIds" label="Reviewers" searchFn={q => api.searchUsers(q)} />
126
+ *
127
+ */
19
128
  export declare function TfMultipleIdSearchInput({ isDisabled, ...props }: Omit<React.ComponentProps<typeof MultipleIdSearchInput>, 'value' | 'onChange'>): import("react/jsx-runtime").JSX.Element;
20
129
  export {};
@@ -1,2 +1,2 @@
1
- import{jsx as n,jsxs as c}from"react/jsx-runtime";import{useQuery as N}from"@tanstack/react-query";import{useId as b,useState as M}from"react";import{Autocomplete as x}from"react-aria-components";import{Button as F}from"./button.js";import{Loader as B}from"./loader.js";import{Menu as T,MenuItem as j}from"./menu.js";import{PopoverTrigger as A,Popover as E}from"./popover.js";import{SearchField as K}from"./searchfield.js";import{useTfFieldContext as h,getFieldErrorMessage as p}from"../utilities/form.js";import{FormField as L}from"./field.js";import"class-variance-authority";import"../utilities/theme.js";import"clsx";import"./icons.js";import"./list-box.js";import"./select.js";import"../utilities/form-context.js";import"@tanstack/react-form";function f({label:r,description:t,errorMessage:e,searchFn:o,isDisabled:a,onBlur:g,onChange:P,value:s,renderLabel:S,...y}){const I=b(),[l,C]=M(""),{data:m,isError:d,isFetching:u,error:v}=N({queryKey:[I,l],queryFn:()=>o(l)});return n("div",{className:"group form-field",children:n(L,{label:r,description:t,errorMessage:e,children:c(A,{onOpenChange:i=>{i||g?.(s)},children:[n(F,{className:"min-w-3xs",isDisabled:a,children:S(s,m)}),n(E,{className:"p-2",children:c(x,{inputValue:l,onInputChange:C,children:[n(K,{className:"mb-2",autoFocus:!0}),u&&n("div",{className:"p-input",children:n(B,{className:"mx-auto"})}),!u&&!d&&n(T,{...y,className:"max-h-48",items:m,renderEmptyState:()=>n("div",{className:"body-sm p-2",children:"No results found."}),children:i=>n(j,{id:i.id,children:i.name},i.id)}),d&&n("div",{className:"text-destructive p-icon body-sm",children:v.message})]})})]})})})}function _({...r}){return n(f,{selectedKeys:[r.value],onSelectionChange:t=>r.onChange(Array.from(t).filter(e=>typeof e=="string")[0]),renderLabel:(t,e)=>e?.find(o=>o.id===t)?.name??t,selectionMode:"single",...r})}function q({...r}){return n(f,{selectedKeys:r.value,onSelectionChange:t=>r.onChange(Array.from(t).filter(e=>typeof e=="string")),selectionMode:"multiple",renderLabel:(t,e)=>t.map(o=>e?.find(a=>a.id===o)?.name??o).join(","),...r})}function ne({isDisabled:r,...t}){const e=h({disabled:r});return n(_,{...t,isDisabled:r||e.form.state.isSubmitting,value:e.state.value,onBlur:o=>e.handleBlur(),onChange:o=>e.handleChange(o),errorMessage:p(e)})}function te({isDisabled:r,...t}){const e=h({disabled:r});return n(q,{...t,isDisabled:r||e.form.state.isSubmitting,value:e.state.value,onBlur:o=>e.handleBlur(),onChange:o=>e.handleChange(o),errorMessage:p(e)})}export{q as MultipleIdSearchInput,_ as SingleIdSearchInput,te as TfMultipleIdSearchInput,ne as TfSingleIdSearchInput};
1
+ import{jsx as n,jsxs as c}from"react/jsx-runtime";import{useQuery as N}from"@tanstack/react-query";import{useId as b,useState as M}from"react";import{Autocomplete as x}from"react-aria-components";import{Button as F}from"./button.js";import{Loader as B}from"./loader.js";import{Menu as j,MenuItem as A}from"./menu.js";import{PopoverTrigger as E,Popover as K}from"./popover.js";import{SearchField as L}from"./searchfield.js";import{getFieldErrorMessage as h}from"../utilities/form.js";import{useFieldContext as p}from"../utilities/form-context.js";import{FormField as T}from"./field.js";import"class-variance-authority";import"../utilities/theme.js";import"clsx";import"./icons.js";import"./list-box.js";import"./select.js";import"@tanstack/react-form";function f({label:r,description:t,errorMessage:e,searchFn:o,isDisabled:a,onBlur:g,onChange:P,value:s,renderLabel:S,...y}){const I=b(),[l,C]=M(""),{data:m,isError:d,isFetching:u,error:v}=N({queryKey:[I,l],queryFn:()=>o(l)});return n("div",{className:"group form-field",children:n(T,{label:r,description:t,errorMessage:e,children:c(E,{onOpenChange:i=>{i||g?.(s)},children:[n(F,{className:"min-w-3xs",isDisabled:a,children:S(s,m)}),n(K,{className:"p-2",children:c(x,{inputValue:l,onInputChange:C,children:[n(L,{className:"mb-2",autoFocus:!0}),u&&n("div",{className:"p-input",children:n(B,{className:"mx-auto"})}),!u&&!d&&n(j,{...y,className:"max-h-48",items:m,renderEmptyState:()=>n("div",{className:"body-sm p-2",children:"No results found."}),children:i=>n(A,{id:i.id,children:i.name},i.id)}),d&&n("div",{className:"text-destructive p-icon body-sm",children:v.message})]})})]})})})}function _({...r}){return n(f,{selectedKeys:[r.value],onSelectionChange:t=>r.onChange(Array.from(t).filter(e=>typeof e=="string")[0]),renderLabel:(t,e)=>e?.find(o=>o.id===t)?.name??t,selectionMode:"single",...r})}function q({...r}){return n(f,{selectedKeys:r.value,onSelectionChange:t=>r.onChange(Array.from(t).filter(e=>typeof e=="string")),selectionMode:"multiple",renderLabel:(t,e)=>t.map(o=>e?.find(a=>a.id===o)?.name??o).join(","),...r})}function ne({isDisabled:r,...t}){const e=p({disabled:r});return n(_,{...t,isDisabled:r||e.form.state.isSubmitting,value:e.state.value,onBlur:o=>e.handleBlur(),onChange:o=>e.handleChange(o),errorMessage:h(e)})}function te({isDisabled:r,...t}){const e=p({disabled:r});return n(q,{...t,isDisabled:r||e.form.state.isSubmitting,value:e.state.value,onBlur:o=>e.handleBlur(),onChange:o=>e.handleChange(o),errorMessage:h(e)})}export{q as MultipleIdSearchInput,_ as SingleIdSearchInput,te as TfMultipleIdSearchInput,ne as TfSingleIdSearchInput};
2
2
  //# sourceMappingURL=id-search.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"id-search.js","sources":["../../lib/components/id-search.tsx"],"sourcesContent":["import { useQuery } from '@tanstack/react-query';\nimport { useId, useState } from 'react';\nimport { Autocomplete } from 'react-aria-components';\nimport { Button } from '../components/button';\nimport { Loader } from '../components/loader';\nimport { Menu, MenuItem } from '../components/menu';\nimport { Popover, PopoverTrigger } from '../components/popover';\nimport { SearchField } from '../components/searchfield';\nimport { getFieldErrorMessage, useTfFieldContext } from '../utilities/form';\nimport { FormField, type FormFieldProps } from './field';\n\ntype BaseSearchableResource = {\n id: string;\n name: string;\n};\n\nfunction BaseIdSearchInput<T extends BaseSearchableResource, V>({\n label,\n description,\n errorMessage,\n searchFn,\n isDisabled,\n onBlur,\n onChange,\n value,\n renderLabel,\n ...props\n}: FormFieldProps & {\n searchFn: (q: string) => Promise<T[] | undefined>;\n isDisabled?: boolean;\n accessor: keyof BaseSearchableResource;\n value: V;\n onBlur?: (v: V) => void;\n onChange: (v: V) => void;\n renderLabel: (v: V, data: T[] | undefined) => string;\n} & Omit<React.ComponentProps<typeof Menu>, 'items' | 'className'>) {\n const id = useId();\n const [search, _setSearch] = useState('');\n const { data, isError, isFetching, error } = useQuery({\n queryKey: [id, search],\n queryFn: () => searchFn(search),\n });\n\n return (\n <div className=\"group form-field\">\n <FormField label={label} description={description} errorMessage={errorMessage}>\n <PopoverTrigger\n onOpenChange={o => {\n if (!o) {\n // searchInputRef.current?.focus();\n onBlur?.(value);\n }\n }}\n >\n <Button className={'min-w-3xs'} isDisabled={isDisabled}>\n {renderLabel(value, data)}\n </Button>\n <Popover className={'p-2'}>\n <Autocomplete inputValue={search} onInputChange={_setSearch}>\n <SearchField className={'mb-2'} autoFocus />\n {isFetching && (\n <div className=\"p-input\">\n <Loader className=\"mx-auto\" />\n </div>\n )}\n {!isFetching && !isError && (\n <Menu\n {...props}\n className={'max-h-48'}\n items={data}\n renderEmptyState={() => <div className=\"body-sm p-2\">No results found.</div>}\n >\n {item => (\n <MenuItem key={item['id']} id={item['id']}>\n {item.name}\n </MenuItem>\n )}\n </Menu>\n )}\n {isError && <div className=\"text-destructive p-icon body-sm\">{error.message}</div>}\n </Autocomplete>\n </Popover>\n </PopoverTrigger>\n </FormField>\n </div>\n );\n}\n\nexport function SingleIdSearchInput<T extends BaseSearchableResource>({\n ...props\n}: Omit<\n React.ComponentProps<typeof BaseIdSearchInput<T, string>>,\n 'onSelectionChange' | 'selectionMode' | 'selectedKeys' | 'renderLabel'\n>) {\n return (\n <BaseIdSearchInput\n selectedKeys={[props.value]}\n onSelectionChange={e => props.onChange(Array.from(e).filter(v => typeof v === 'string')[0])}\n renderLabel={(v, d) => d?.find(di => di.id === v)?.name ?? v}\n selectionMode=\"single\"\n {...props}\n />\n );\n}\n\nexport function MultipleIdSearchInput<T extends BaseSearchableResource>({\n ...props\n}: Omit<\n React.ComponentProps<typeof BaseIdSearchInput<T, string[]>>,\n 'renderLabel' | 'onSelectionChange' | 'selectionMode' | 'selectedKeys'\n>) {\n return (\n <BaseIdSearchInput\n selectedKeys={props.value}\n onSelectionChange={e => props.onChange(Array.from(e).filter(v => typeof v === 'string'))}\n selectionMode=\"multiple\"\n renderLabel={(v, d) => v.map(vi => d?.find(di => di.id === vi)?.name ?? vi).join(',')}\n {...props}\n />\n );\n}\n\nexport function TfSingleIdSearchInput({\n isDisabled,\n ...props\n}: Omit<React.ComponentProps<typeof SingleIdSearchInput>, 'value' | 'onChange'>) {\n const field = useTfFieldContext<string>({ disabled: isDisabled });\n return (\n <SingleIdSearchInput\n {...props}\n isDisabled={isDisabled || field.form.state.isSubmitting}\n value={field.state.value}\n onBlur={_ => field.handleBlur()}\n onChange={e => field.handleChange(e)}\n errorMessage={getFieldErrorMessage(field)}\n />\n );\n}\n// TODO, popover alignment should be same as Select\nexport function TfMultipleIdSearchInput({\n isDisabled,\n ...props\n}: Omit<React.ComponentProps<typeof MultipleIdSearchInput>, 'value' | 'onChange'>) {\n const field = useTfFieldContext<string[]>({ disabled: isDisabled });\n return (\n <MultipleIdSearchInput\n {...props}\n isDisabled={isDisabled || field.form.state.isSubmitting}\n value={field.state.value}\n onBlur={_ => field.handleBlur()}\n onChange={e => field.handleChange(e)}\n errorMessage={getFieldErrorMessage(field)}\n />\n );\n}\n"],"names":["BaseIdSearchInput","label","description","errorMessage","searchFn","isDisabled","onBlur","onChange","value","renderLabel","props","id","useId","search","_setSearch","useState","data","isError","isFetching","error","useQuery","jsx","FormField","jsxs","PopoverTrigger","o","Button","Popover","Autocomplete","SearchField","Loader","Menu","item","MenuItem","SingleIdSearchInput","e","v","d","di","MultipleIdSearchInput","vi","TfSingleIdSearchInput","field","useTfFieldContext","_","getFieldErrorMessage","TfMultipleIdSearchInput"],"mappings":"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"}
1
+ {"version":3,"file":"id-search.js","sources":["../../lib/components/id-search.tsx"],"sourcesContent":["import { useQuery } from '@tanstack/react-query';\nimport { useId, useState } from 'react';\nimport { Autocomplete } from 'react-aria-components';\nimport { Button } from '../components/button';\nimport { Loader } from '../components/loader';\nimport { Menu, MenuItem } from '../components/menu';\nimport { Popover, PopoverTrigger } from '../components/popover';\nimport { SearchField } from '../components/searchfield';\nimport { getFieldErrorMessage } from '../utilities/form';\nimport { useFieldContext } from '../utilities/form-context';\nimport { FormField, type FormFieldProps } from './field';\n\n/**\n * Minimal resource shape used by the ID search inputs.\n * Only `id` and `name` are required.\n *\n * @example\n * const user: BaseSearchableResource = { id: 'u_123', name: 'Nabeel Farooq' };\n */\ntype BaseSearchableResource = {\n /** Unique identifier used as the input value. */\n id: string;\n /** Human-readable label shown to users. */\n name: string;\n};\n\n/**\n * - Generic, accessible ID-search building block.\n * - Search (powered by react-query)\n * - Renders an accessible Autocomplete + Menu listbox\n * - Exposes a controlled `value`/`onChange` contract so callers (and wrappers) can manage state\n * - Clear separation of concerns: this component only handles UI search/display; callers provide `searchFn`\n *\n * @template T - resource type extending `BaseSearchableResource` (must have `id` and `name`)\n * @template V - controlled value type (e.g. `string` for single-select or `string[]` for multi-select)\n *\n * @param props - props object (see inline property JSDoc for the most important fields)\n *\n * @remarks\n * - `searchFn` should return `Promise<T[] | undefined>`. Returning `undefined` indicates no results / handled error.\n * - When the popover closes, `onBlur` (if provided) is called with the current `value`.\n * - `renderLabel` must convert `value` to a readable string for the control button.\n *\n * @example\n * <BaseIdSearchInput\n * label=\"Owner\"\n * searchFn={q => api.searchUsers(q)}\n * value={ownerId}\n * onChange={setOwnerId}\n * renderLabel={(v, data) => data?.find(d => d.id === v)?.name ?? v}\n * />\n *\n * @testing\n * - Mock `searchFn` in unit tests; assert keyboard navigation, open/close behavior, and `onBlur` call on popover close.\n */\nfunction BaseIdSearchInput<T extends BaseSearchableResource, V>({\n label,\n description,\n errorMessage,\n searchFn,\n isDisabled,\n onBlur,\n onChange,\n value,\n renderLabel,\n ...props\n}: FormFieldProps & {\n /** Function that returns matching resources for the current query. */\n searchFn: (q: string) => Promise<T[] | undefined>;\n /** Disable interactions. */\n isDisabled?: boolean;\n /** Key used to access an alternate display accessor on item (kept for compatibility). */\n accessor: keyof BaseSearchableResource;\n /** Controlled value. */\n value: V;\n /** Called when popover closes or the field blurs with the current value. */\n onBlur?: (v: V) => void;\n /** Controlled change handler. */\n onChange: (v: V) => void;\n /** Render a human-readable label for the current value using the latest data. */\n renderLabel: (v: V, data: T[] | undefined) => string;\n} & Omit<React.ComponentProps<typeof Menu>, 'items' | 'className'>) {\n const id = useId();\n const [search, _setSearch] = useState('');\n const { data, isError, isFetching, error } = useQuery({\n queryKey: [id, search],\n queryFn: () => searchFn(search),\n });\n\n return (\n <div className=\"group form-field\">\n <FormField label={label} description={description} errorMessage={errorMessage}>\n <PopoverTrigger\n onOpenChange={o => {\n if (!o) {\n // searchInputRef.current?.focus();\n onBlur?.(value);\n }\n }}\n >\n <Button className={'min-w-3xs'} isDisabled={isDisabled}>\n {renderLabel(value, data)}\n </Button>\n <Popover className={'p-2'}>\n <Autocomplete inputValue={search} onInputChange={_setSearch}>\n <SearchField className={'mb-2'} autoFocus />\n {isFetching && (\n <div className=\"p-input\">\n <Loader className=\"mx-auto\" />\n </div>\n )}\n {!isFetching && !isError && (\n <Menu\n {...props}\n className={'max-h-48'}\n items={data}\n renderEmptyState={() => <div className=\"body-sm p-2\">No results found.</div>}\n >\n {item => (\n <MenuItem key={item['id']} id={item['id']}>\n {item.name}\n </MenuItem>\n )}\n </Menu>\n )}\n {isError && <div className=\"text-destructive p-icon body-sm\">{error.message}</div>}\n </Autocomplete>\n </Popover>\n </PopoverTrigger>\n </FormField>\n </div>\n );\n}\n\n/**\n * Single-selection ID search input.\n *\n * Thin, typed wrapper around `BaseIdSearchInput` specialized for the very common single-ID case.\n * Adapts the internal selection events into `onChange(id?: string)` and renders the selected label.\n *\n * @template T - resource type (extends BaseSearchableResource)\n *\n * @param props - Inherits `BaseIdSearchInput` props but uses `string[]` value type.\n *\n * @example\n * <SingleIdSearchInput\n * label=\"Reporter\"\n * value={reporterId}\n * onChange={setReporterId}\n * searchFn={q => api.searchUsers(q)}\n * />\n *\n */\nexport function SingleIdSearchInput<T extends BaseSearchableResource>({\n ...props\n}: Omit<\n React.ComponentProps<typeof BaseIdSearchInput<T, string>>,\n 'onSelectionChange' | 'selectionMode' | 'selectedKeys' | 'renderLabel'\n>) {\n return (\n <BaseIdSearchInput\n selectedKeys={[props.value]}\n onSelectionChange={e => props.onChange(Array.from(e).filter(v => typeof v === 'string')[0])}\n renderLabel={(v, d) => d?.find(di => di.id === v)?.name ?? v}\n selectionMode=\"single\"\n {...props}\n />\n );\n}\n\n/**\n * Multi-selection ID search input.\n *\n * Thin wrapper around `BaseIdSearchInput` for the multiple-ID (`string[]`) case.\n * Adapts internal selection events into `onChange(ids: string[])`.\n *\n * @template T - resource type (extends BaseSearchableResource)\n *\n * @param props - Inherits `BaseIdSearchInput` props but uses `string[]` value type.\n *\n * @example\n * <MultipleIdSearchInput\n * label=\"Reviewers\"\n * value={reviewerIds}\n * onChange={setReviewerIds}\n * searchFn={q => api.searchUsers(q)}\n * />\n *\n * @remarks\n * - The `renderLabel` joins selected item names with commas for compact display.\n */\nexport function MultipleIdSearchInput<T extends BaseSearchableResource>({\n ...props\n}: Omit<\n React.ComponentProps<typeof BaseIdSearchInput<T, string[]>>,\n 'renderLabel' | 'onSelectionChange' | 'selectionMode' | 'selectedKeys'\n>) {\n return (\n <BaseIdSearchInput\n selectedKeys={props.value}\n onSelectionChange={e => props.onChange(Array.from(e).filter(v => typeof v === 'string'))}\n selectionMode=\"multiple\"\n renderLabel={(v, d) => v.map(vi => d?.find(di => di.id === vi)?.name ?? vi).join(',')}\n {...props}\n />\n );\n}\n\n/**\n * Form-integrated single-select ID input (field wrapper).\n *\n * Integrates `SingleIdSearchInput` into the form system using `useFieldContext`.\n * - wires `value`, `onChange`, and `onBlur`\n * - disables the control while the form is submitting\n * - surfaces field-level error messages\n *\n * @example\n * <TfSingleIdSearchInput name=\"ownerId\" label=\"Owner\" searchFn={q => api.searchUsers(q)} />\n \n */\nexport function TfSingleIdSearchInput({\n isDisabled,\n ...props\n}: Omit<React.ComponentProps<typeof SingleIdSearchInput>, 'value' | 'onChange'>) {\n const field = useFieldContext<string>({ disabled: isDisabled });\n return (\n <SingleIdSearchInput\n {...props}\n isDisabled={isDisabled || field.form.state.isSubmitting}\n value={field.state.value}\n onBlur={_ => field.handleBlur()}\n onChange={e => field.handleChange(e)}\n errorMessage={getFieldErrorMessage(field)}\n />\n );\n}\n// TODO, popover alignment should be same as Select\n\n/**\n * Form-integrated multi-select ID input (field wrapper).\n *\n * Integrates `MultipleIdSearchInput` into the form system using `useFieldContext`.\n * - wires `value`, `onChange`, and `onBlur`\n * - disables the control while the form is submitting\n * - surfaces field-level error messages\n *\n * @example\n * <TfMultipleIdSearchInput name=\"reviewerIds\" label=\"Reviewers\" searchFn={q => api.searchUsers(q)} />\n *\n */\nexport function TfMultipleIdSearchInput({\n isDisabled,\n ...props\n}: Omit<React.ComponentProps<typeof MultipleIdSearchInput>, 'value' | 'onChange'>) {\n const field = useFieldContext<string[]>({ disabled: isDisabled });\n return (\n <MultipleIdSearchInput\n {...props}\n isDisabled={isDisabled || field.form.state.isSubmitting}\n value={field.state.value}\n onBlur={_ => field.handleBlur()}\n onChange={e => field.handleChange(e)}\n errorMessage={getFieldErrorMessage(field)}\n />\n );\n}\n"],"names":["BaseIdSearchInput","label","description","errorMessage","searchFn","isDisabled","onBlur","onChange","value","renderLabel","props","id","useId","search","_setSearch","useState","data","isError","isFetching","error","useQuery","jsx","FormField","jsxs","PopoverTrigger","o","Button","Popover","Autocomplete","SearchField","Loader","Menu","item","MenuItem","SingleIdSearchInput","e","v","d","di","MultipleIdSearchInput","vi","TfSingleIdSearchInput","field","useFieldContext","_","getFieldErrorMessage","TfMultipleIdSearchInput"],"mappings":"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"}
@@ -1,2 +1,2 @@
1
- import{jsx as i}from"react/jsx-runtime";import{FormField as d}from"./field.js";import{EasyMenu as a,MenuItem as p}from"./menu.js";import{useTfFieldContext as f,getFieldErrorMessage as u}from"../utilities/form.js";import"class-variance-authority";import"react-aria-components";import"../utilities/theme.js";import"clsx";import"./icons.js";import"react";import"./button.js";import"./loader.js";import"./list-box.js";import"./select.js";import"./popover.js";import"../utilities/form-context.js";import"@tanstack/react-form";function c({items:o,value:e,onChange:t,label:l,errorMessage:n,description:s,...m}){return i("div",{className:"group form-field",children:i(d,{label:l,description:s,errorMessage:n,children:i(a,{isNonModal:!1,selectionMode:"multiple",selectedKeys:e,onSelectionChange:r=>{typeof r!="string"&&t(r)},items:o,label:e.size,...m,children:r=>i(p,{id:r.id,isDisabled:r?.disabled,children:r.label},r.id)})})})}function A({...o}){const e=f({disabled:o.isDisabled});return i(c,{value:new Set(e.state.value),onChange:t=>e.setValue(Array.from(t)),onClose:e.handleBlur,errorMessage:u(e),...o})}export{c as MultiSelect,A as TfMultiSelect};
1
+ import{jsx as i}from"react/jsx-runtime";import{FormField as d}from"./field.js";import{EasyMenu as a,MenuItem as p}from"./menu.js";import{getFieldErrorMessage as f}from"../utilities/form.js";import{useFieldContext as u}from"../utilities/form-context.js";import"class-variance-authority";import"react-aria-components";import"../utilities/theme.js";import"clsx";import"./icons.js";import"react";import"./button.js";import"./loader.js";import"./list-box.js";import"./select.js";import"./popover.js";import"@tanstack/react-form";function c({items:o,value:e,onChange:t,label:l,errorMessage:n,description:m,...s}){return i("div",{className:"group form-field",children:i(d,{label:l,description:m,errorMessage:n,children:i(a,{isNonModal:!1,selectionMode:"multiple",selectedKeys:e,onSelectionChange:r=>{typeof r!="string"&&t(r)},items:o,label:e.size,...s,children:r=>i(p,{id:r.id,isDisabled:r?.disabled,children:r.label},r.id)})})})}function B({...o}){const e=u({disabled:o.isDisabled});return i(c,{value:new Set(e.state.value),onChange:t=>e.setValue(Array.from(t)),onClose:e.handleBlur,errorMessage:f(e),...o})}export{c as MultiSelect,B as TfMultiSelect};
2
2
  //# sourceMappingURL=multi-select.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"multi-select.js","sources":["../../lib/components/multi-select.tsx"],"sourcesContent":["import React from 'react';\nimport { FormField, type FormFieldProps } from '../components/field';\nimport { EasyMenu, MenuItem } from '../components/menu';\nimport type { SelectOption } from '../components/select-options';\nimport { getFieldErrorMessage, useTfFieldContext } from '../utilities/form';\n\ninterface MultipleSelectionProps {\n value: Set<string | number>;\n onChange: (v: Set<string | number>) => void;\n buttonLabel?: React.ReactNode;\n items: SelectOption[];\n}\n\nexport interface MultiSelectProps\n extends MultipleSelectionProps,\n FormFieldProps,\n Omit<React.ComponentProps<typeof EasyMenu>, 'label' | 'items'> {}\n\nexport function MultiSelect({\n items,\n value,\n onChange: setValue,\n label,\n errorMessage,\n description,\n ...props\n}: MultiSelectProps) {\n return (\n <div className=\"group form-field\">\n <FormField {...{ label, description, errorMessage }}>\n <EasyMenu\n isNonModal={false}\n selectionMode=\"multiple\"\n selectedKeys={value}\n onSelectionChange={v => {\n if (typeof v === 'string') return;\n setValue(v);\n }}\n items={items}\n label={value.size}\n {...props}\n >\n {item => (\n <MenuItem id={item.id} key={item.id} isDisabled={item?.disabled}>\n {item.label}\n </MenuItem>\n )}\n </EasyMenu>\n </FormField>\n </div>\n );\n}\n\nexport interface TfMultiSelectProps extends Omit<MultiSelectProps, 'value' | 'onChange'> {}\nexport function TfMultiSelect({ ...props }: TfMultiSelectProps) {\n const field = useTfFieldContext<string[]>({\n disabled: props.isDisabled,\n });\n\n return (\n <MultiSelect\n value={new Set(field.state.value)}\n // @ts-expect-error\n onChange={e => field.setValue(Array.from(e))}\n onClose={field.handleBlur}\n errorMessage={getFieldErrorMessage(field)}\n {...props}\n />\n );\n}\n"],"names":["MultiSelect","items","value","setValue","label","errorMessage","description","props","jsx","FormField","EasyMenu","v","item","MenuItem","TfMultiSelect","field","useTfFieldContext","e","getFieldErrorMessage"],"mappings":"ygBAkBO,SAASA,EAAY,CACxB,MAAAC,EACA,MAAAC,EACA,SAAUC,EACV,MAAAC,EACA,aAAAC,EACA,YAAAC,EACA,GAAGC,CACP,EAAqB,CACjB,OACIC,EAAC,MAAA,CAAI,UAAU,mBACX,SAAAA,EAACC,EAAA,CAAgB,MAAAL,EAAO,YAAAE,EAAa,aAAAD,EACjC,SAAAG,EAACE,EAAA,CACG,WAAY,GACZ,cAAc,WACd,aAAcR,EACd,kBAAmBS,GAAK,CAChB,OAAOA,GAAM,UACjBR,EAASQ,CAAC,CACd,EACA,MAAAV,EACA,MAAOC,EAAM,KACZ,GAAGK,EAEH,SAAAK,GACGJ,EAACK,EAAA,CAAS,GAAID,EAAK,GAAkB,WAAYA,GAAM,SAClD,SAAAA,EAAK,KAAA,EADkBA,EAAK,EAEjC,CAAA,CAAA,EAGZ,CAAA,CACJ,CAER,CAGO,SAASE,EAAc,CAAE,GAAGP,GAA6B,CAC5D,MAAMQ,EAAQC,EAA4B,CACtC,SAAUT,EAAM,UAAA,CACnB,EAED,OACIC,EAACR,EAAA,CACG,MAAO,IAAI,IAAIe,EAAM,MAAM,KAAK,EAEhC,SAAUE,GAAKF,EAAM,SAAS,MAAM,KAAKE,CAAC,CAAC,EAC3C,QAASF,EAAM,WACf,aAAcG,EAAqBH,CAAK,EACvC,GAAGR,CAAA,CAAA,CAGhB"}
1
+ {"version":3,"file":"multi-select.js","sources":["../../lib/components/multi-select.tsx"],"sourcesContent":["import React from 'react';\nimport { FormField, type FormFieldProps } from '../components/field';\nimport { EasyMenu, MenuItem } from '../components/menu';\nimport type { SelectOption } from '../components/select-options';\nimport { getFieldErrorMessage } from '../utilities/form';\nimport { useFieldContext } from '../utilities/form-context';\n\ninterface MultipleSelectionProps {\n value: Set<string | number>;\n onChange: (v: Set<string | number>) => void;\n buttonLabel?: React.ReactNode;\n items: SelectOption[];\n}\n\nexport interface MultiSelectProps\n extends MultipleSelectionProps,\n FormFieldProps,\n Omit<React.ComponentProps<typeof EasyMenu>, 'label' | 'items'> {}\n\nexport function MultiSelect({\n items,\n value,\n onChange: setValue,\n label,\n errorMessage,\n description,\n ...props\n}: MultiSelectProps) {\n return (\n <div className=\"group form-field\">\n <FormField {...{ label, description, errorMessage }}>\n <EasyMenu\n isNonModal={false}\n selectionMode=\"multiple\"\n selectedKeys={value}\n onSelectionChange={v => {\n if (typeof v === 'string') return;\n setValue(v);\n }}\n items={items}\n label={value.size}\n {...props}\n >\n {item => (\n <MenuItem id={item.id} key={item.id} isDisabled={item?.disabled}>\n {item.label}\n </MenuItem>\n )}\n </EasyMenu>\n </FormField>\n </div>\n );\n}\n\nexport interface TfMultiSelectProps extends Omit<MultiSelectProps, 'value' | 'onChange'> {}\nexport function TfMultiSelect({ ...props }: TfMultiSelectProps) {\n const field = useFieldContext<string[]>({\n disabled: props.isDisabled,\n });\n\n return (\n <MultiSelect\n value={new Set(field.state.value)}\n // @ts-expect-error\n onChange={e => field.setValue(Array.from(e))}\n onClose={field.handleBlur}\n errorMessage={getFieldErrorMessage(field)}\n {...props}\n />\n );\n}\n"],"names":["MultiSelect","items","value","setValue","label","errorMessage","description","props","jsx","FormField","EasyMenu","v","item","MenuItem","TfMultiSelect","field","useFieldContext","e","getFieldErrorMessage"],"mappings":"4gBAmBO,SAASA,EAAY,CACxB,MAAAC,EACA,MAAAC,EACA,SAAUC,EACV,MAAAC,EACA,aAAAC,EACA,YAAAC,EACA,GAAGC,CACP,EAAqB,CACjB,OACIC,EAAC,MAAA,CAAI,UAAU,mBACX,SAAAA,EAACC,EAAA,CAAgB,MAAAL,EAAO,YAAAE,EAAa,aAAAD,EACjC,SAAAG,EAACE,EAAA,CACG,WAAY,GACZ,cAAc,WACd,aAAcR,EACd,kBAAmBS,GAAK,CAChB,OAAOA,GAAM,UACjBR,EAASQ,CAAC,CACd,EACA,MAAAV,EACA,MAAOC,EAAM,KACZ,GAAGK,EAEH,SAAAK,GACGJ,EAACK,EAAA,CAAS,GAAID,EAAK,GAAkB,WAAYA,GAAM,SAClD,SAAAA,EAAK,KAAA,EADkBA,EAAK,EAEjC,CAAA,CAAA,EAGZ,CAAA,CACJ,CAER,CAGO,SAASE,EAAc,CAAE,GAAGP,GAA6B,CAC5D,MAAMQ,EAAQC,EAA0B,CACpC,SAAUT,EAAM,UAAA,CACnB,EAED,OACIC,EAACR,EAAA,CACG,MAAO,IAAI,IAAIe,EAAM,MAAM,KAAK,EAEhC,SAAUE,GAAKF,EAAM,SAAS,MAAM,KAAKE,CAAC,CAAC,EAC3C,QAASF,EAAM,WACf,aAAcG,EAAqBH,CAAK,EACvC,GAAGR,CAAA,CAAA,CAGhB"}
@@ -1,2 +1,2 @@
1
- import{jsx as r,jsxs as d}from"react/jsx-runtime";import{NumberField as c,composeRenderProps as n,Input as p}from"react-aria-components";import{Button as f}from"./button.js";import{useTfFieldContext as b,getFieldErrorMessage as l}from"../utilities/form.js";import{classNames as i}from"../utilities/theme.js";import{FormField as h,FieldGroup as N}from"./field.js";import{IcUp as g,IcDown as F}from"./icons.js";import"class-variance-authority";import"./loader.js";import"react";import"../utilities/form-context.js";import"@tanstack/react-form";import"clsx";const x=c;function v({className:o,...t}){return r(p,{className:n(o,e=>i("w-fit min-w-0 flex-1 border-r border-transparent bg-popover pr-2 outline-0 placeholder:text-muted-foreground [&::-webkit-search-cancel-button]:hidden",e)),...t})}function w({className:o,...t}){return d("div",{className:i("absolute right-0 flex h-full flex-col border-l",o),...t,children:[r(m,{slot:"increment",children:r(g,{"aria-hidden":!0,className:"size-icon"})}),r("div",{className:"border-b"}),r(m,{slot:"decrement",children:r(F,{"aria-hidden":!0,className:"size-icon"})})]})}function m({className:o,...t}){return r(f,{className:n(o,e=>i("w-auto grow h-3 px-0.5 text-muted-foreground",e)),variant:"ghost",size:"none",...t})}function I({label:o,description:t,errorMessage:e,className:s,...a}){return r(x,{className:n(s,u=>i("group form-field",u)),...a,children:r(h,{label:o,description:t,errorMessage:e,children:d(N,{children:[r(v,{}),r(w,{})]})})})}function R({isDisabled:o,...t}){const e=b({disabled:o});return r(I,{isInvalid:!!l(e),isDisabled:o||e.form.state.isSubmitting,value:e.state.value,id:e.name,onChange:e.handleChange,onBlur:e.handleBlur,errorMessage:l(e),...t})}export{I as NumberField,R as TfNumberField};
1
+ import{jsx as r,jsxs as d}from"react/jsx-runtime";import{NumberField as c,composeRenderProps as n,Input as p}from"react-aria-components";import{Button as f}from"./button.js";import{getFieldErrorMessage as l}from"../utilities/form.js";import{useFieldContext as b}from"../utilities/form-context.js";import{classNames as i}from"../utilities/theme.js";import{FormField as h,FieldGroup as N}from"./field.js";import{IcUp as g,IcDown as F}from"./icons.js";import"class-variance-authority";import"./loader.js";import"@tanstack/react-form";import"react";import"clsx";const x=c;function v({className:o,...t}){return r(p,{className:n(o,e=>i("w-fit min-w-0 flex-1 border-r border-transparent bg-popover pr-2 outline-0 placeholder:text-muted-foreground [&::-webkit-search-cancel-button]:hidden",e)),...t})}function w({className:o,...t}){return d("div",{className:i("absolute right-0 flex h-full flex-col border-l",o),...t,children:[r(m,{slot:"increment",children:r(g,{"aria-hidden":!0,className:"size-icon"})}),r("div",{className:"border-b"}),r(m,{slot:"decrement",children:r(F,{"aria-hidden":!0,className:"size-icon"})})]})}function m({className:o,...t}){return r(f,{className:n(o,e=>i("w-auto grow h-3 px-0.5 text-muted-foreground",e)),variant:"ghost",size:"none",...t})}function I({label:o,description:t,errorMessage:e,className:s,...a}){return r(x,{className:n(s,u=>i("group form-field",u)),...a,children:r(h,{label:o,description:t,errorMessage:e,children:d(N,{children:[r(v,{}),r(w,{})]})})})}function T({isDisabled:o,...t}){const e=b({disabled:o});return r(I,{isInvalid:!!l(e),isDisabled:o||e.form.state.isSubmitting,value:e.state.value,id:e.name,onChange:e.handleChange,onBlur:e.handleBlur,errorMessage:l(e),...t})}export{I as NumberField,T as TfNumberField};
2
2
  //# sourceMappingURL=numberfield.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"numberfield.js","sources":["../../lib/components/numberfield.tsx"],"sourcesContent":["import {\n ButtonProps as AriaButtonProps,\n Input as AriaInput,\n InputProps as AriaInputProps,\n NumberField as AriaNumberField,\n NumberFieldProps as AriaNumberFieldProps,\n composeRenderProps,\n} from 'react-aria-components';\n\nimport { Button } from '../components/button';\nimport { getFieldErrorMessage, useTfFieldContext } from '../utilities/form';\nimport { classNames } from '../utilities/theme';\nimport { FieldGroup, FormField, type FormFieldProps } from './field';\nimport { IcDown, IcUp } from './icons';\n\nconst ANumberField = AriaNumberField;\n\nfunction NumberFieldInput({ className, ...props }: AriaInputProps) {\n return (\n <AriaInput\n className={composeRenderProps(className, className =>\n classNames(\n 'w-fit min-w-0 flex-1 border-r border-transparent bg-popover pr-2 outline-0 placeholder:text-muted-foreground [&::-webkit-search-cancel-button]:hidden',\n className\n )\n )}\n {...props}\n />\n );\n}\n\nfunction NumberFieldSteppers({ className, ...props }: React.ComponentProps<'div'>) {\n return (\n <div className={classNames('absolute right-0 flex h-full flex-col border-l', className)} {...props}>\n <NumberFieldStepper slot=\"increment\">\n <IcUp aria-hidden className=\"size-icon\" />\n </NumberFieldStepper>\n <div className=\"border-b\" />\n <NumberFieldStepper slot=\"decrement\">\n <IcDown aria-hidden className=\"size-icon\" />\n </NumberFieldStepper>\n </div>\n );\n}\n\nfunction NumberFieldStepper({ className, ...props }: AriaButtonProps) {\n return (\n <Button\n className={composeRenderProps(className, className =>\n classNames('w-auto grow h-3 px-0.5 text-muted-foreground', className)\n )}\n variant={'ghost'}\n size={'none'}\n {...props}\n />\n );\n}\n\ntype NumberFieldProps = AriaNumberFieldProps & FormFieldProps;\nexport function NumberField({ label, description, errorMessage, className, ...props }: NumberFieldProps) {\n return (\n <ANumberField\n className={composeRenderProps(className, className => classNames('group form-field', className))}\n {...props}\n >\n <FormField label={label} description={description} errorMessage={errorMessage}>\n <FieldGroup>\n <NumberFieldInput />\n <NumberFieldSteppers />\n </FieldGroup>\n </FormField>\n </ANumberField>\n );\n}\n\nexport function TfNumberField({\n isDisabled,\n ...props\n}: Omit<React.ComponentProps<typeof NumberField>, 'value' | 'id' | 'onChange' | 'onBlur'>) {\n const field = useTfFieldContext<number>({ disabled: isDisabled });\n\n return (\n <NumberField\n isInvalid={!!getFieldErrorMessage(field)}\n isDisabled={isDisabled || field.form.state.isSubmitting}\n value={field.state.value}\n id={field.name}\n onChange={field.handleChange}\n onBlur={field.handleBlur}\n errorMessage={getFieldErrorMessage(field)}\n {...props}\n />\n );\n}\n"],"names":["ANumberField","AriaNumberField","NumberFieldInput","className","props","jsx","AriaInput","composeRenderProps","classNames","NumberFieldSteppers","jsxs","NumberFieldStepper","IcUp","IcDown","Button","NumberField","label","description","errorMessage","FormField","FieldGroup","TfNumberField","isDisabled","field","useTfFieldContext","getFieldErrorMessage"],"mappings":"2iBAeA,MAAMA,EAAeC,EAErB,SAASC,EAAiB,CAAE,UAAAC,EAAW,GAAGC,GAAyB,CAC/D,OACIC,EAACC,EAAA,CACG,UAAWC,EAAmBJ,EAAWA,GACrCK,EACI,wJACAL,CAAA,CACJ,EAEH,GAAGC,CAAA,CAAA,CAGhB,CAEA,SAASK,EAAoB,CAAE,UAAAN,EAAW,GAAGC,GAAsC,CAC/E,OACIM,EAAC,OAAI,UAAWF,EAAW,iDAAkDL,CAAS,EAAI,GAAGC,EACzF,SAAA,CAAAC,EAACM,EAAA,CAAmB,KAAK,YACrB,SAAAN,EAACO,GAAK,cAAW,GAAC,UAAU,WAAA,CAAY,CAAA,CAC5C,EACAP,EAAC,MAAA,CAAI,UAAU,UAAA,CAAW,EAC1BA,EAACM,EAAA,CAAmB,KAAK,YACrB,SAAAN,EAACQ,GAAO,cAAW,GAAC,UAAU,WAAA,CAAY,CAAA,CAC9C,CAAA,EACJ,CAER,CAEA,SAASF,EAAmB,CAAE,UAAAR,EAAW,GAAGC,GAA0B,CAClE,OACIC,EAACS,EAAA,CACG,UAAWP,EAAmBJ,EAAWA,GACrCK,EAAW,+CAAgDL,CAAS,CAAA,EAExE,QAAS,QACT,KAAM,OACL,GAAGC,CAAA,CAAA,CAGhB,CAGO,SAASW,EAAY,CAAE,MAAAC,EAAO,YAAAC,EAAa,aAAAC,EAAc,UAAAf,EAAW,GAAGC,GAA2B,CACrG,OACIC,EAACL,EAAA,CACG,UAAWO,EAAmBJ,EAAWA,GAAaK,EAAW,mBAAoBL,CAAS,CAAC,EAC9F,GAAGC,EAEJ,WAACe,EAAA,CAAU,MAAAH,EAAc,YAAAC,EAA0B,aAAAC,EAC/C,WAACE,EAAA,CACG,SAAA,CAAAf,EAACH,EAAA,EAAiB,IACjBO,EAAA,CAAA,CAAoB,CAAA,CAAA,CACzB,CAAA,CACJ,CAAA,CAAA,CAGZ,CAEO,SAASY,EAAc,CAC1B,WAAAC,EACA,GAAGlB,CACP,EAA2F,CACvF,MAAMmB,EAAQC,EAA0B,CAAE,SAAUF,EAAY,EAEhE,OACIjB,EAACU,EAAA,CACG,UAAW,CAAC,CAACU,EAAqBF,CAAK,EACvC,WAAYD,GAAcC,EAAM,KAAK,MAAM,aAC3C,MAAOA,EAAM,MAAM,MACnB,GAAIA,EAAM,KACV,SAAUA,EAAM,aAChB,OAAQA,EAAM,WACd,aAAcE,EAAqBF,CAAK,EACvC,GAAGnB,CAAA,CAAA,CAGhB"}
1
+ {"version":3,"file":"numberfield.js","sources":["../../lib/components/numberfield.tsx"],"sourcesContent":["import {\n ButtonProps as AriaButtonProps,\n Input as AriaInput,\n InputProps as AriaInputProps,\n NumberField as AriaNumberField,\n NumberFieldProps as AriaNumberFieldProps,\n composeRenderProps,\n} from 'react-aria-components';\n\nimport { Button } from '../components/button';\nimport { getFieldErrorMessage } from '../utilities/form';\nimport { useFieldContext } from '../utilities/form-context';\nimport { classNames } from '../utilities/theme';\nimport { FieldGroup, FormField, type FormFieldProps } from './field';\nimport { IcDown, IcUp } from './icons';\n\nconst ANumberField = AriaNumberField;\n\nfunction NumberFieldInput({ className, ...props }: AriaInputProps) {\n return (\n <AriaInput\n className={composeRenderProps(className, className =>\n classNames(\n 'w-fit min-w-0 flex-1 border-r border-transparent bg-popover pr-2 outline-0 placeholder:text-muted-foreground [&::-webkit-search-cancel-button]:hidden',\n className\n )\n )}\n {...props}\n />\n );\n}\n\nfunction NumberFieldSteppers({ className, ...props }: React.ComponentProps<'div'>) {\n return (\n <div className={classNames('absolute right-0 flex h-full flex-col border-l', className)} {...props}>\n <NumberFieldStepper slot=\"increment\">\n <IcUp aria-hidden className=\"size-icon\" />\n </NumberFieldStepper>\n <div className=\"border-b\" />\n <NumberFieldStepper slot=\"decrement\">\n <IcDown aria-hidden className=\"size-icon\" />\n </NumberFieldStepper>\n </div>\n );\n}\n\nfunction NumberFieldStepper({ className, ...props }: AriaButtonProps) {\n return (\n <Button\n className={composeRenderProps(className, className =>\n classNames('w-auto grow h-3 px-0.5 text-muted-foreground', className)\n )}\n variant={'ghost'}\n size={'none'}\n {...props}\n />\n );\n}\n\ntype NumberFieldProps = AriaNumberFieldProps & FormFieldProps;\nexport function NumberField({ label, description, errorMessage, className, ...props }: NumberFieldProps) {\n return (\n <ANumberField\n className={composeRenderProps(className, className => classNames('group form-field', className))}\n {...props}\n >\n <FormField label={label} description={description} errorMessage={errorMessage}>\n <FieldGroup>\n <NumberFieldInput />\n <NumberFieldSteppers />\n </FieldGroup>\n </FormField>\n </ANumberField>\n );\n}\n\nexport function TfNumberField({\n isDisabled,\n ...props\n}: Omit<React.ComponentProps<typeof NumberField>, 'value' | 'id' | 'onChange' | 'onBlur'>) {\n const field = useFieldContext<number>({ disabled: isDisabled });\n\n return (\n <NumberField\n isInvalid={!!getFieldErrorMessage(field)}\n isDisabled={isDisabled || field.form.state.isSubmitting}\n value={field.state.value}\n id={field.name}\n onChange={field.handleChange}\n onBlur={field.handleBlur}\n errorMessage={getFieldErrorMessage(field)}\n {...props}\n />\n );\n}\n"],"names":["ANumberField","AriaNumberField","NumberFieldInput","className","props","jsx","AriaInput","composeRenderProps","classNames","NumberFieldSteppers","jsxs","NumberFieldStepper","IcUp","IcDown","Button","NumberField","label","description","errorMessage","FormField","FieldGroup","TfNumberField","isDisabled","field","useFieldContext","getFieldErrorMessage"],"mappings":"8iBAgBA,MAAMA,EAAeC,EAErB,SAASC,EAAiB,CAAE,UAAAC,EAAW,GAAGC,GAAyB,CAC/D,OACIC,EAACC,EAAA,CACG,UAAWC,EAAmBJ,EAAWA,GACrCK,EACI,wJACAL,CAAA,CACJ,EAEH,GAAGC,CAAA,CAAA,CAGhB,CAEA,SAASK,EAAoB,CAAE,UAAAN,EAAW,GAAGC,GAAsC,CAC/E,OACIM,EAAC,OAAI,UAAWF,EAAW,iDAAkDL,CAAS,EAAI,GAAGC,EACzF,SAAA,CAAAC,EAACM,EAAA,CAAmB,KAAK,YACrB,SAAAN,EAACO,GAAK,cAAW,GAAC,UAAU,WAAA,CAAY,CAAA,CAC5C,EACAP,EAAC,MAAA,CAAI,UAAU,UAAA,CAAW,EAC1BA,EAACM,EAAA,CAAmB,KAAK,YACrB,SAAAN,EAACQ,GAAO,cAAW,GAAC,UAAU,WAAA,CAAY,CAAA,CAC9C,CAAA,EACJ,CAER,CAEA,SAASF,EAAmB,CAAE,UAAAR,EAAW,GAAGC,GAA0B,CAClE,OACIC,EAACS,EAAA,CACG,UAAWP,EAAmBJ,EAAWA,GACrCK,EAAW,+CAAgDL,CAAS,CAAA,EAExE,QAAS,QACT,KAAM,OACL,GAAGC,CAAA,CAAA,CAGhB,CAGO,SAASW,EAAY,CAAE,MAAAC,EAAO,YAAAC,EAAa,aAAAC,EAAc,UAAAf,EAAW,GAAGC,GAA2B,CACrG,OACIC,EAACL,EAAA,CACG,UAAWO,EAAmBJ,EAAWA,GAAaK,EAAW,mBAAoBL,CAAS,CAAC,EAC9F,GAAGC,EAEJ,WAACe,EAAA,CAAU,MAAAH,EAAc,YAAAC,EAA0B,aAAAC,EAC/C,WAACE,EAAA,CACG,SAAA,CAAAf,EAACH,EAAA,EAAiB,IACjBO,EAAA,CAAA,CAAoB,CAAA,CAAA,CACzB,CAAA,CACJ,CAAA,CAAA,CAGZ,CAEO,SAASY,EAAc,CAC1B,WAAAC,EACA,GAAGlB,CACP,EAA2F,CACvF,MAAMmB,EAAQC,EAAwB,CAAE,SAAUF,EAAY,EAE9D,OACIjB,EAACU,EAAA,CACG,UAAW,CAAC,CAACU,EAAqBF,CAAK,EACvC,WAAYD,GAAcC,EAAM,KAAK,MAAM,aAC3C,MAAOA,EAAM,MAAM,MACnB,GAAIA,EAAM,KACV,SAAUA,EAAM,aAChB,OAAQA,EAAM,WACd,aAAcE,EAAqBF,CAAK,EACvC,GAAGnB,CAAA,CAAA,CAGhB"}
@@ -1,2 +1,2 @@
1
- import{jsx as i}from"react/jsx-runtime";import{TextField as r}from"./textfield.js";import"react-aria-components";import"../utilities/form.js";import"react";import"../utilities/form-context.js";import"@tanstack/react-form";import"../utilities/theme.js";import"clsx";import"./field.js";import"class-variance-authority";import"./icons.js";function j({className:m,...t}){return i(r,{inputClassName:"justify-items-center",...t})}export{j as OTPField};
1
+ import{jsx as i}from"react/jsx-runtime";import{TextField as r}from"./textfield.js";import"react-aria-components";import"../utilities/form.js";import"../utilities/form-context.js";import"@tanstack/react-form";import"react";import"../utilities/theme.js";import"clsx";import"./field.js";import"class-variance-authority";import"./icons.js";function j({className:m,...t}){return i(r,{inputClassName:"justify-items-center",...t})}export{j as OTPField};
2
2
  //# sourceMappingURL=otpfield.js.map
@@ -1,2 +1,2 @@
1
- "use client";import{jsx as o,jsxs as c,Fragment as u}from"react/jsx-runtime";import{Select as p,composeRenderProps as i,SelectValue as f,ListBox as S}from"react-aria-components";import{Button as h}from"./button.js";import{FormField as g}from"./field.js";import{useTfFieldContext as x,getFieldErrorMessage as B}from"../utilities/form.js";import{classNames as l}from"../utilities/theme.js";import{IcDown as N}from"./icons.js";import{ListBoxItem as w,ListBoxHeader as C,ListBoxCollection as F}from"./list-box.js";import{Popover as L}from"./popover.js";import"class-variance-authority";import"./loader.js";import"clsx";import"react";import"../utilities/form-context.js";import"@tanstack/react-form";const v=p,b=w,Q=C,U=F,I=({className:r,...t})=>o(f,{className:i(r,e=>l("line-clamp-1 data-[placeholder]:text-muted-foreground","[&>[slot=description]]:hidden",e)),...t});function P({className:r,children:t,...e}){return o(h,{...e,children:i(t,n=>c(u,{children:[n,o(N,{"aria-hidden":"true",className:"size-icon opacity-50"})]}))})}function T({className:r,...t}){return o(L,{className:i(r,e=>l("w-auto min-w-[--trigger-width]",e)),...t})}function V({className:r,...t}){return o(S,{className:i(r,e=>l("overflow-auto p-1 outline-none",e)),...t})}function j({label:r,description:t,errorMessage:e,children:n,className:s,items:a,...m}){return o(v,{className:i(s,d=>l("group form-field",d)),...m,children:c(g,{label:r,description:t,errorMessage:e,children:[o(P,{children:o(I,{})}),o(T,{children:o(V,{items:a,children:n})})]})})}function W({...r}){const t=x({disabled:r.isDisabled});return o(j,{selectedKey:t.state.value,onSelectionChange:e=>t.handleChange(e.toString()),onBlur:t.handleBlur,errorMessage:B(t),...r,children:e=>o(b,{id:e.id,children:e.label},e.id)})}export{U as SelectCollection,Q as SelectHeader,b as SelectItem,T as SelectPopover,I as SelectValue,j as SingleSelect,W as TfSingleSelect};
1
+ "use client";import{jsx as o,jsxs as c,Fragment as u}from"react/jsx-runtime";import{Select as p,composeRenderProps as i,SelectValue as f,ListBox as S}from"react-aria-components";import{Button as h}from"./button.js";import{FormField as g}from"./field.js";import{getFieldErrorMessage as x}from"../utilities/form.js";import{useFieldContext as B}from"../utilities/form-context.js";import{classNames as l}from"../utilities/theme.js";import{IcDown as N}from"./icons.js";import{ListBoxItem as w,ListBoxHeader as C,ListBoxCollection as F}from"./list-box.js";import{Popover as L}from"./popover.js";import"class-variance-authority";import"./loader.js";import"clsx";import"react";import"@tanstack/react-form";const v=p,b=w,Q=C,U=F,I=({className:r,...t})=>o(f,{className:i(r,e=>l("line-clamp-1 data-[placeholder]:text-muted-foreground","[&>[slot=description]]:hidden",e)),...t});function P({className:r,children:t,...e}){return o(h,{...e,children:i(t,n=>c(u,{children:[n,o(N,{"aria-hidden":"true",className:"size-icon opacity-50"})]}))})}function V({className:r,...t}){return o(L,{className:i(r,e=>l("w-auto min-w-[--trigger-width]",e)),...t})}function j({className:r,...t}){return o(S,{className:i(r,e=>l("overflow-auto p-1 outline-none",e)),...t})}function y({label:r,description:t,errorMessage:e,children:n,className:s,items:a,...m}){return o(v,{className:i(s,d=>l("group form-field",d)),...m,children:c(g,{label:r,description:t,errorMessage:e,children:[o(P,{children:o(I,{})}),o(V,{children:o(j,{items:a,children:n})})]})})}function W({...r}){const t=B({disabled:r.isDisabled});return o(y,{selectedKey:t.state.value,onSelectionChange:e=>t.handleChange(e.toString()),onBlur:t.handleBlur,errorMessage:x(t),...r,children:e=>o(b,{id:e.id,children:e.label},e.id)})}export{U as SelectCollection,Q as SelectHeader,b as SelectItem,V as SelectPopover,I as SelectValue,y as SingleSelect,W as TfSingleSelect};
2
2
  //# sourceMappingURL=select.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"select.js","sources":["../../lib/components/select.tsx"],"sourcesContent":["'use client';\nimport {\n ListBox as AriaListBox,\n ListBoxProps as AriaListBoxProps,\n PopoverProps as AriaPopoverProps,\n Select as AriaSelect,\n SelectProps as AriaSelectProps,\n SelectValue as AriaSelectValue,\n SelectValueProps as AriaSelectValueProps,\n composeRenderProps,\n} from 'react-aria-components';\n\nimport { Button } from '../components/button';\nimport { FormField, type FormFieldProps } from '../components/field';\nimport type { SelectOption } from '../components/select-options';\nimport { getFieldErrorMessage, useTfFieldContext } from '../utilities/form';\nimport { classNames } from '../utilities/theme';\nimport { IcDown } from './icons';\nimport { ListBoxCollection, ListBoxHeader, ListBoxItem } from './list-box';\nimport { Popover } from './popover';\n\nconst ASelect = AriaSelect;\nexport const SelectItem = ListBoxItem;\nexport const SelectHeader = ListBoxHeader;\nexport const SelectCollection = ListBoxCollection;\n\nexport const SelectValue = <T extends object>({ className, ...props }: AriaSelectValueProps<T>) => (\n <AriaSelectValue\n className={composeRenderProps(className, className =>\n classNames(\n 'line-clamp-1 data-[placeholder]:text-muted-foreground',\n /* Description */\n '[&>[slot=description]]:hidden',\n className\n )\n )}\n {...props}\n />\n);\n// TODO, justify-between?\nfunction SelectTrigger({ className, children, ...props }: React.ComponentProps<typeof Button>) {\n return (\n <Button {...props}>\n {composeRenderProps(children, children => (\n <>\n {children}\n <IcDown aria-hidden=\"true\" className=\"size-icon opacity-50\" />\n </>\n ))}\n </Button>\n );\n}\n\nexport function SelectPopover({ className, ...props }: AriaPopoverProps) {\n return (\n <Popover\n className={composeRenderProps(className, className =>\n classNames('w-auto min-w-[--trigger-width]', className)\n )}\n {...props}\n />\n );\n}\n\nfunction SelectListBox<T extends object>({ className, ...props }: AriaListBoxProps<T>) {\n return (\n <AriaListBox\n className={composeRenderProps(className, className =>\n classNames('overflow-auto p-1 outline-none', className)\n )}\n {...props}\n />\n );\n}\n\nexport interface SingleSelectProps<T extends SelectOption>\n extends Omit<AriaSelectProps<T>, 'children'>,\n FormFieldProps {\n items: Iterable<T>;\n children: React.ReactNode | ((item: T) => React.ReactNode);\n}\n\nexport function SingleSelect<T extends SelectOption>({\n label,\n description,\n errorMessage,\n children,\n className,\n items,\n ...props\n}: SingleSelectProps<T>) {\n return (\n <ASelect\n className={composeRenderProps(className, className => classNames('group form-field', className))}\n {...props}\n >\n <FormField label={label} description={description} errorMessage={errorMessage}>\n <SelectTrigger>\n <SelectValue />\n </SelectTrigger>\n <SelectPopover>\n <SelectListBox items={items}>{children}</SelectListBox>\n </SelectPopover>\n </FormField>\n </ASelect>\n );\n}\n\ntype TfSingleSelectProps<T extends SelectOption> = Omit<SingleSelectProps<T>, 'value' | 'setValue' | 'children'>;\n\nexport function TfSingleSelect<T extends SelectOption>({ ...props }: TfSingleSelectProps<T>) {\n const field = useTfFieldContext<string>({ disabled: props.isDisabled });\n\n return (\n <SingleSelect\n selectedKey={field.state.value}\n onSelectionChange={e => field.handleChange(e!.toString())}\n onBlur={field.handleBlur}\n errorMessage={getFieldErrorMessage(field)}\n {...props}\n >\n {item => (\n <SelectItem id={item.id} key={item.id}>\n {item.label}\n </SelectItem>\n )}\n </SingleSelect>\n );\n}\n"],"names":["ASelect","AriaSelect","SelectItem","ListBoxItem","SelectHeader","ListBoxHeader","SelectCollection","ListBoxCollection","SelectValue","className","props","jsx","AriaSelectValue","composeRenderProps","classNames","SelectTrigger","children","Button","jsxs","Fragment","IcDown","SelectPopover","Popover","SelectListBox","AriaListBox","SingleSelect","label","description","errorMessage","items","FormField","TfSingleSelect","field","useTfFieldContext","getFieldErrorMessage","item"],"mappings":"urBAqBA,MAAMA,EAAUC,EACHC,EAAaC,EACbC,EAAeC,EACfC,EAAmBC,EAEnBC,EAAc,CAAmB,CAAE,UAAAC,EAAW,GAAGC,KAC1DC,EAACC,EAAA,CACG,UAAWC,EAAmBJ,EAAWA,GACrCK,EACI,wDAEA,gCACAL,CAAA,CACJ,EAEH,GAAGC,CAAA,CACR,EAGJ,SAASK,EAAc,CAAE,UAAAN,EAAW,SAAAO,EAAU,GAAGN,GAA8C,CAC3F,OACIC,EAACM,GAAQ,GAAGP,EACP,WAAmBM,EAAUA,GAC1BE,EAAAC,EAAA,CACK,SAAA,CAAAH,EACDL,EAACS,EAAA,CAAO,cAAY,OAAO,UAAU,sBAAA,CAAuB,CAAA,CAAA,CAChE,CACH,CAAA,CACL,CAER,CAEO,SAASC,EAAc,CAAE,UAAAZ,EAAW,GAAGC,GAA2B,CACrE,OACIC,EAACW,EAAA,CACG,UAAWT,EAAmBJ,EAAWA,GACrCK,EAAW,iCAAkCL,CAAS,CAAA,EAEzD,GAAGC,CAAA,CAAA,CAGhB,CAEA,SAASa,EAAgC,CAAE,UAAAd,EAAW,GAAGC,GAA8B,CACnF,OACIC,EAACa,EAAA,CACG,UAAWX,EAAmBJ,EAAWA,GACrCK,EAAW,iCAAkCL,CAAS,CAAA,EAEzD,GAAGC,CAAA,CAAA,CAGhB,CASO,SAASe,EAAqC,CACjD,MAAAC,EACA,YAAAC,EACA,aAAAC,EACA,SAAAZ,EACA,UAAAP,EACA,MAAAoB,EACA,GAAGnB,CACP,EAAyB,CACrB,OACIC,EAACX,EAAA,CACG,UAAWa,EAAmBJ,EAAWA,GAAaK,EAAW,mBAAoBL,CAAS,CAAC,EAC9F,GAAGC,EAEJ,SAAAQ,EAACY,EAAA,CAAU,MAAAJ,EAAc,YAAAC,EAA0B,aAAAC,EAC/C,SAAA,CAAAjB,EAACI,EAAA,CACG,SAAAJ,EAACH,EAAA,CAAA,CAAY,EACjB,IACCa,EAAA,CACG,SAAAV,EAACY,EAAA,CAAc,MAAAM,EAAe,SAAAb,EAAS,CAAA,CAC3C,CAAA,CAAA,CACJ,CAAA,CAAA,CAGZ,CAIO,SAASe,EAAuC,CAAE,GAAGrB,GAAiC,CACzF,MAAMsB,EAAQC,EAA0B,CAAE,SAAUvB,EAAM,WAAY,EAEtE,OACIC,EAACc,EAAA,CACG,YAAaO,EAAM,MAAM,MACzB,kBAAmB,GAAKA,EAAM,aAAa,EAAG,UAAU,EACxD,OAAQA,EAAM,WACd,aAAcE,EAAqBF,CAAK,EACvC,GAAGtB,EAEH,SAAAyB,KACIjC,EAAA,CAAW,GAAIiC,EAAK,GAChB,SAAAA,EAAK,KAAA,EADoBA,EAAK,EAEnC,CAAA,CAAA,CAIhB"}
1
+ {"version":3,"file":"select.js","sources":["../../lib/components/select.tsx"],"sourcesContent":["'use client';\nimport {\n ListBox as AriaListBox,\n ListBoxProps as AriaListBoxProps,\n PopoverProps as AriaPopoverProps,\n Select as AriaSelect,\n SelectProps as AriaSelectProps,\n SelectValue as AriaSelectValue,\n SelectValueProps as AriaSelectValueProps,\n composeRenderProps,\n} from 'react-aria-components';\n\nimport { Button } from '../components/button';\nimport { FormField, type FormFieldProps } from '../components/field';\nimport type { SelectOption } from '../components/select-options';\nimport { getFieldErrorMessage } from '../utilities/form';\nimport { useFieldContext } from '../utilities/form-context';\nimport { classNames } from '../utilities/theme';\nimport { IcDown } from './icons';\nimport { ListBoxCollection, ListBoxHeader, ListBoxItem } from './list-box';\nimport { Popover } from './popover';\n\nconst ASelect = AriaSelect;\nexport const SelectItem = ListBoxItem;\nexport const SelectHeader = ListBoxHeader;\nexport const SelectCollection = ListBoxCollection;\n\nexport const SelectValue = <T extends object>({ className, ...props }: AriaSelectValueProps<T>) => (\n <AriaSelectValue\n className={composeRenderProps(className, className =>\n classNames(\n 'line-clamp-1 data-[placeholder]:text-muted-foreground',\n /* Description */\n '[&>[slot=description]]:hidden',\n className\n )\n )}\n {...props}\n />\n);\n// TODO, justify-between?\nfunction SelectTrigger({ className, children, ...props }: React.ComponentProps<typeof Button>) {\n return (\n <Button {...props}>\n {composeRenderProps(children, children => (\n <>\n {children}\n <IcDown aria-hidden=\"true\" className=\"size-icon opacity-50\" />\n </>\n ))}\n </Button>\n );\n}\n\nexport function SelectPopover({ className, ...props }: AriaPopoverProps) {\n return (\n <Popover\n className={composeRenderProps(className, className =>\n classNames('w-auto min-w-[--trigger-width]', className)\n )}\n {...props}\n />\n );\n}\n\nfunction SelectListBox<T extends object>({ className, ...props }: AriaListBoxProps<T>) {\n return (\n <AriaListBox\n className={composeRenderProps(className, className =>\n classNames('overflow-auto p-1 outline-none', className)\n )}\n {...props}\n />\n );\n}\n\nexport interface SingleSelectProps<T extends SelectOption>\n extends Omit<AriaSelectProps<T>, 'children'>,\n FormFieldProps {\n items: Iterable<T>;\n children: React.ReactNode | ((item: T) => React.ReactNode);\n}\n\nexport function SingleSelect<T extends SelectOption>({\n label,\n description,\n errorMessage,\n children,\n className,\n items,\n ...props\n}: SingleSelectProps<T>) {\n return (\n <ASelect\n className={composeRenderProps(className, className => classNames('group form-field', className))}\n {...props}\n >\n <FormField label={label} description={description} errorMessage={errorMessage}>\n <SelectTrigger>\n <SelectValue />\n </SelectTrigger>\n <SelectPopover>\n <SelectListBox items={items}>{children}</SelectListBox>\n </SelectPopover>\n </FormField>\n </ASelect>\n );\n}\n\ntype TfSingleSelectProps<T extends SelectOption> = Omit<SingleSelectProps<T>, 'value' | 'setValue' | 'children'>;\n\nexport function TfSingleSelect<T extends SelectOption>({ ...props }: TfSingleSelectProps<T>) {\n const field = useFieldContext<string>({ disabled: props.isDisabled });\n\n return (\n <SingleSelect\n selectedKey={field.state.value}\n onSelectionChange={e => field.handleChange(e!.toString())}\n onBlur={field.handleBlur}\n errorMessage={getFieldErrorMessage(field)}\n {...props}\n >\n {item => (\n <SelectItem id={item.id} key={item.id}>\n {item.label}\n </SelectItem>\n )}\n </SingleSelect>\n );\n}\n"],"names":["ASelect","AriaSelect","SelectItem","ListBoxItem","SelectHeader","ListBoxHeader","SelectCollection","ListBoxCollection","SelectValue","className","props","jsx","AriaSelectValue","composeRenderProps","classNames","SelectTrigger","children","Button","jsxs","Fragment","IcDown","SelectPopover","Popover","SelectListBox","AriaListBox","SingleSelect","label","description","errorMessage","items","FormField","TfSingleSelect","field","useFieldContext","getFieldErrorMessage","item"],"mappings":"0rBAsBA,MAAMA,EAAUC,EACHC,EAAaC,EACbC,EAAeC,EACfC,EAAmBC,EAEnBC,EAAc,CAAmB,CAAE,UAAAC,EAAW,GAAGC,KAC1DC,EAACC,EAAA,CACG,UAAWC,EAAmBJ,EAAWA,GACrCK,EACI,wDAEA,gCACAL,CAAA,CACJ,EAEH,GAAGC,CAAA,CACR,EAGJ,SAASK,EAAc,CAAE,UAAAN,EAAW,SAAAO,EAAU,GAAGN,GAA8C,CAC3F,OACIC,EAACM,GAAQ,GAAGP,EACP,WAAmBM,EAAUA,GAC1BE,EAAAC,EAAA,CACK,SAAA,CAAAH,EACDL,EAACS,EAAA,CAAO,cAAY,OAAO,UAAU,sBAAA,CAAuB,CAAA,CAAA,CAChE,CACH,CAAA,CACL,CAER,CAEO,SAASC,EAAc,CAAE,UAAAZ,EAAW,GAAGC,GAA2B,CACrE,OACIC,EAACW,EAAA,CACG,UAAWT,EAAmBJ,EAAWA,GACrCK,EAAW,iCAAkCL,CAAS,CAAA,EAEzD,GAAGC,CAAA,CAAA,CAGhB,CAEA,SAASa,EAAgC,CAAE,UAAAd,EAAW,GAAGC,GAA8B,CACnF,OACIC,EAACa,EAAA,CACG,UAAWX,EAAmBJ,EAAWA,GACrCK,EAAW,iCAAkCL,CAAS,CAAA,EAEzD,GAAGC,CAAA,CAAA,CAGhB,CASO,SAASe,EAAqC,CACjD,MAAAC,EACA,YAAAC,EACA,aAAAC,EACA,SAAAZ,EACA,UAAAP,EACA,MAAAoB,EACA,GAAGnB,CACP,EAAyB,CACrB,OACIC,EAACX,EAAA,CACG,UAAWa,EAAmBJ,EAAWA,GAAaK,EAAW,mBAAoBL,CAAS,CAAC,EAC9F,GAAGC,EAEJ,SAAAQ,EAACY,EAAA,CAAU,MAAAJ,EAAc,YAAAC,EAA0B,aAAAC,EAC/C,SAAA,CAAAjB,EAACI,EAAA,CACG,SAAAJ,EAACH,EAAA,CAAA,CAAY,EACjB,IACCa,EAAA,CACG,SAAAV,EAACY,EAAA,CAAc,MAAAM,EAAe,SAAAb,EAAS,CAAA,CAC3C,CAAA,CAAA,CACJ,CAAA,CAAA,CAGZ,CAIO,SAASe,EAAuC,CAAE,GAAGrB,GAAiC,CACzF,MAAMsB,EAAQC,EAAwB,CAAE,SAAUvB,EAAM,WAAY,EAEpE,OACIC,EAACc,EAAA,CACG,YAAaO,EAAM,MAAM,MACzB,kBAAmB,GAAKA,EAAM,aAAa,EAAG,UAAU,EACxD,OAAQA,EAAM,WACd,aAAcE,EAAqBF,CAAK,EACvC,GAAGtB,EAEH,SAAAyB,KACIjC,EAAA,CAAW,GAAIiC,EAAK,GAChB,SAAAA,EAAK,KAAA,EADoBA,EAAK,EAEnC,CAAA,CAAA,CAIhB"}
@@ -1,2 +1,2 @@
1
- import{jsx as t}from"react/jsx-runtime";import{TextField as f,composeRenderProps as i,TextArea as p,Input as c}from"react-aria-components";import{useTfFieldContext as g,getFieldErrorMessage as l}from"../utilities/form.js";import{classNames as n}from"../utilities/theme.js";import{FormField as b}from"./field.js";import"react";import"../utilities/form-context.js";import"@tanstack/react-form";import"clsx";import"class-variance-authority";import"./icons.js";const x=f;function T({className:r,...o}){return t(c,{className:i(r,e=>n("flex input-dim w-full border border-input bg-popover ring-offset-background file:border-0 file:bg-transparent file:body-sm file:font-medium placeholder:text-muted-foreground","disabled-muted","focus-ring",e)),...o})}function h({className:r,...o}){return t(p,{className:i(r,e=>n("flex min-h-32 w-full border border-input bg-popover px-3 py-2 body-sm ring-offset-background placeholder:text-muted-foreground","focus-ring","disabled-muted",e)),...o})}function F({label:r,description:o,errorMessage:e,textArea:a,className:m,inputClassName:d,...s}){return t(x,{className:i(m,u=>n("group form-field",u)),...s,children:t(b,{label:r,errorMessage:e,description:o,children:a?t(h,{className:d}):t(T,{className:d})})})}function j({isDisabled:r,...o}){const e=g({disabled:r});return t(F,{isDisabled:r||e.form.state.isSubmitting,value:e.state.value,id:e.name,name:e.name,onBlur:e.handleBlur,onChange:e.handleChange,isInvalid:!!l(e),errorMessage:l(e),...o})}export{F as TextField,j as TfTextField};
1
+ import{jsx as t}from"react/jsx-runtime";import{TextField as f,composeRenderProps as i,TextArea as p,Input as c}from"react-aria-components";import{getFieldErrorMessage as l}from"../utilities/form.js";import{useFieldContext as g}from"../utilities/form-context.js";import{classNames as n}from"../utilities/theme.js";import{FormField as b}from"./field.js";import"@tanstack/react-form";import"react";import"clsx";import"class-variance-authority";import"./icons.js";const x=f;function h({className:r,...o}){return t(c,{className:i(r,e=>n("flex input-dim w-full border border-input bg-popover ring-offset-background file:border-0 file:bg-transparent file:body-sm file:font-medium placeholder:text-muted-foreground","disabled-muted","focus-ring",e)),...o})}function F({className:r,...o}){return t(p,{className:i(r,e=>n("flex min-h-32 w-full border border-input bg-popover px-3 py-2 body-sm ring-offset-background placeholder:text-muted-foreground","focus-ring","disabled-muted",e)),...o})}function T({label:r,description:o,errorMessage:e,textArea:m,className:a,inputClassName:d,...s}){return t(x,{className:i(a,u=>n("group form-field",u)),...s,children:t(b,{label:r,errorMessage:e,description:o,children:m?t(F,{className:d}):t(h,{className:d})})})}function j({isDisabled:r,...o}){const e=g({disabled:r});return t(T,{isDisabled:r||e.form.state.isSubmitting,value:e.state.value,id:e.name,name:e.name,onBlur:e.handleBlur,onChange:e.handleChange,isInvalid:!!l(e),errorMessage:l(e),...o})}export{T as TextField,j as TfTextField};
2
2
  //# sourceMappingURL=textfield.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"textfield.js","sources":["../../lib/components/textfield.tsx"],"sourcesContent":["import {\n Input as AriaInput,\n InputProps as AriaInputProps,\n TextArea as AriaTextArea,\n TextAreaProps as AriaTextAreaProps,\n TextField as AriaTextField,\n TextFieldProps as AriaTextFieldProps,\n composeRenderProps,\n} from 'react-aria-components';\nimport { getFieldErrorMessage, useTfFieldContext } from '../utilities/form';\nimport { classNames } from '../utilities/theme';\nimport { FormField, type FormFieldProps } from './field';\n\nconst ATextField = AriaTextField;\n\nfunction Input({ className, ...props }: AriaInputProps) {\n return (\n <AriaInput\n className={composeRenderProps(className, className =>\n classNames(\n 'flex input-dim w-full border border-input bg-popover ring-offset-background file:border-0 file:bg-transparent file:body-sm file:font-medium placeholder:text-muted-foreground',\n /* Disabled */\n 'disabled-muted',\n /* Focused */\n 'focus-ring',\n className\n )\n )}\n {...props}\n />\n );\n}\n\nfunction TextArea({ className, ...props }: AriaTextAreaProps) {\n return (\n <AriaTextArea\n className={composeRenderProps(className, className =>\n classNames(\n 'flex min-h-32 w-full border border-input bg-popover px-3 py-2 body-sm ring-offset-background placeholder:text-muted-foreground',\n /* Focused */\n 'focus-ring',\n /* Disabled */\n 'disabled-muted',\n className\n )\n )}\n {...props}\n />\n );\n}\n\nexport interface TextFieldProps extends AriaTextFieldProps, FormFieldProps {\n textArea?: boolean;\n inputClassName?: string;\n}\n\nexport function TextField({\n label,\n description,\n errorMessage,\n textArea,\n className,\n inputClassName,\n ...props\n}: TextFieldProps) {\n return (\n <ATextField\n className={composeRenderProps(className, className => classNames('group form-field', className))}\n {...props}\n >\n <FormField label={label} errorMessage={errorMessage} description={description}>\n {textArea ? <TextArea className={inputClassName} /> : <Input className={inputClassName} />}\n </FormField>\n </ATextField>\n );\n}\n\nexport function TfTextField({ isDisabled, ...props }: React.ComponentProps<typeof TextField>) {\n const field = useTfFieldContext<string>({ disabled: isDisabled });\n\n return (\n <TextField\n isDisabled={isDisabled || field.form.state.isSubmitting}\n value={field.state.value}\n id={field.name}\n name={field.name}\n onBlur={field.handleBlur}\n onChange={field.handleChange}\n isInvalid={!!getFieldErrorMessage(field)}\n errorMessage={getFieldErrorMessage(field)}\n {...props}\n />\n );\n}\n"],"names":["ATextField","AriaTextField","Input","className","props","jsx","AriaInput","composeRenderProps","classNames","TextArea","AriaTextArea","TextField","label","description","errorMessage","textArea","inputClassName","FormField","TfTextField","isDisabled","field","useTfFieldContext","getFieldErrorMessage"],"mappings":"ycAaA,MAAMA,EAAaC,EAEnB,SAASC,EAAM,CAAE,UAAAC,EAAW,GAAGC,GAAyB,CACpD,OACIC,EAACC,EAAA,CACG,UAAWC,EAAmBJ,EAAWA,GACrCK,EACI,gLAEA,iBAEA,aACAL,CAAA,CACJ,EAEH,GAAGC,CAAA,CAAA,CAGhB,CAEA,SAASK,EAAS,CAAE,UAAAN,EAAW,GAAGC,GAA4B,CAC1D,OACIC,EAACK,EAAA,CACG,UAAWH,EAAmBJ,EAAWA,GACrCK,EACI,iIAEA,aAEA,iBACAL,CAAA,CACJ,EAEH,GAAGC,CAAA,CAAA,CAGhB,CAOO,SAASO,EAAU,CACtB,MAAAC,EACA,YAAAC,EACA,aAAAC,EACA,SAAAC,EACA,UAAAZ,EACA,eAAAa,EACA,GAAGZ,CACP,EAAmB,CACf,OACIC,EAACL,EAAA,CACG,UAAWO,EAAmBJ,EAAWA,GAAaK,EAAW,mBAAoBL,CAAS,CAAC,EAC9F,GAAGC,EAEJ,SAAAC,EAACY,EAAA,CAAU,MAAAL,EAAc,aAAAE,EAA4B,YAAAD,EAChD,SAAAE,EAAWV,EAACI,EAAA,CAAS,UAAWO,EAAgB,EAAKX,EAACH,EAAA,CAAM,UAAWc,EAAgB,CAAA,CAC5F,CAAA,CAAA,CAGZ,CAEO,SAASE,EAAY,CAAE,WAAAC,EAAY,GAAGf,GAAiD,CAC1F,MAAMgB,EAAQC,EAA0B,CAAE,SAAUF,EAAY,EAEhE,OACId,EAACM,EAAA,CACG,WAAYQ,GAAcC,EAAM,KAAK,MAAM,aAC3C,MAAOA,EAAM,MAAM,MACnB,GAAIA,EAAM,KACV,KAAMA,EAAM,KACZ,OAAQA,EAAM,WACd,SAAUA,EAAM,aAChB,UAAW,CAAC,CAACE,EAAqBF,CAAK,EACvC,aAAcE,EAAqBF,CAAK,EACvC,GAAGhB,CAAA,CAAA,CAGhB"}
1
+ {"version":3,"file":"textfield.js","sources":["../../lib/components/textfield.tsx"],"sourcesContent":["import {\n Input as AriaInput,\n InputProps as AriaInputProps,\n TextArea as AriaTextArea,\n TextAreaProps as AriaTextAreaProps,\n TextField as AriaTextField,\n TextFieldProps as AriaTextFieldProps,\n composeRenderProps,\n} from 'react-aria-components';\nimport { getFieldErrorMessage } from '../utilities/form';\nimport { useFieldContext } from '../utilities/form-context';\nimport { classNames } from '../utilities/theme';\nimport { FormField, type FormFieldProps } from './field';\n\nconst ATextField = AriaTextField;\n\nfunction Input({ className, ...props }: AriaInputProps) {\n return (\n <AriaInput\n className={composeRenderProps(className, className =>\n classNames(\n 'flex input-dim w-full border border-input bg-popover ring-offset-background file:border-0 file:bg-transparent file:body-sm file:font-medium placeholder:text-muted-foreground',\n /* Disabled */\n 'disabled-muted',\n /* Focused */\n 'focus-ring',\n className\n )\n )}\n {...props}\n />\n );\n}\n\nfunction TextArea({ className, ...props }: AriaTextAreaProps) {\n return (\n <AriaTextArea\n className={composeRenderProps(className, className =>\n classNames(\n 'flex min-h-32 w-full border border-input bg-popover px-3 py-2 body-sm ring-offset-background placeholder:text-muted-foreground',\n /* Focused */\n 'focus-ring',\n /* Disabled */\n 'disabled-muted',\n className\n )\n )}\n {...props}\n />\n );\n}\n\nexport interface TextFieldProps extends AriaTextFieldProps, FormFieldProps {\n textArea?: boolean;\n inputClassName?: string;\n}\n\nexport function TextField({\n label,\n description,\n errorMessage,\n textArea,\n className,\n inputClassName,\n ...props\n}: TextFieldProps) {\n return (\n <ATextField\n className={composeRenderProps(className, className => classNames('group form-field', className))}\n {...props}\n >\n <FormField label={label} errorMessage={errorMessage} description={description}>\n {textArea ? <TextArea className={inputClassName} /> : <Input className={inputClassName} />}\n </FormField>\n </ATextField>\n );\n}\n\nexport function TfTextField({ isDisabled, ...props }: React.ComponentProps<typeof TextField>) {\n const field = useFieldContext<string>({ disabled: isDisabled });\n\n return (\n <TextField\n isDisabled={isDisabled || field.form.state.isSubmitting}\n value={field.state.value}\n id={field.name}\n name={field.name}\n onBlur={field.handleBlur}\n onChange={field.handleChange}\n isInvalid={!!getFieldErrorMessage(field)}\n errorMessage={getFieldErrorMessage(field)}\n {...props}\n />\n );\n}\n"],"names":["ATextField","AriaTextField","Input","className","props","jsx","AriaInput","composeRenderProps","classNames","TextArea","AriaTextArea","TextField","label","description","errorMessage","textArea","inputClassName","FormField","TfTextField","isDisabled","field","useFieldContext","getFieldErrorMessage"],"mappings":"4cAcA,MAAMA,EAAaC,EAEnB,SAASC,EAAM,CAAE,UAAAC,EAAW,GAAGC,GAAyB,CACpD,OACIC,EAACC,EAAA,CACG,UAAWC,EAAmBJ,EAAWA,GACrCK,EACI,gLAEA,iBAEA,aACAL,CAAA,CACJ,EAEH,GAAGC,CAAA,CAAA,CAGhB,CAEA,SAASK,EAAS,CAAE,UAAAN,EAAW,GAAGC,GAA4B,CAC1D,OACIC,EAACK,EAAA,CACG,UAAWH,EAAmBJ,EAAWA,GACrCK,EACI,iIAEA,aAEA,iBACAL,CAAA,CACJ,EAEH,GAAGC,CAAA,CAAA,CAGhB,CAOO,SAASO,EAAU,CACtB,MAAAC,EACA,YAAAC,EACA,aAAAC,EACA,SAAAC,EACA,UAAAZ,EACA,eAAAa,EACA,GAAGZ,CACP,EAAmB,CACf,OACIC,EAACL,EAAA,CACG,UAAWO,EAAmBJ,EAAWA,GAAaK,EAAW,mBAAoBL,CAAS,CAAC,EAC9F,GAAGC,EAEJ,SAAAC,EAACY,EAAA,CAAU,MAAAL,EAAc,aAAAE,EAA4B,YAAAD,EAChD,SAAAE,EAAWV,EAACI,EAAA,CAAS,UAAWO,EAAgB,EAAKX,EAACH,EAAA,CAAM,UAAWc,EAAgB,CAAA,CAC5F,CAAA,CAAA,CAGZ,CAEO,SAASE,EAAY,CAAE,WAAAC,EAAY,GAAGf,GAAiD,CAC1F,MAAMgB,EAAQC,EAAwB,CAAE,SAAUF,EAAY,EAE9D,OACId,EAACM,EAAA,CACG,WAAYQ,GAAcC,EAAM,KAAK,MAAM,aAC3C,MAAOA,EAAM,MAAM,MACnB,GAAIA,EAAM,KACV,KAAMA,EAAM,KACZ,OAAQA,EAAM,WACd,SAAUA,EAAM,aAChB,UAAW,CAAC,CAACE,EAAqBF,CAAK,EACvC,aAAcE,EAAqBF,CAAK,EACvC,GAAGhB,CAAA,CAAA,CAGhB"}
@@ -1,4 +1,13 @@
1
1
  /**
2
2
  * useFieldContext is used in custom components
3
3
  */
4
- export declare const fieldContext: import('react').Context<import('@tanstack/react-form').AnyFieldApi>, formContext: import('react').Context<import('@tanstack/react-form').AnyFormApi>, useFieldContext: <TData>() => import('@tanstack/react-form').FieldApi<any, string, TData, any, any, any, any, any, any, any, any, any, any, any, any, any, any, any, any>;
4
+ declare const fieldContext: import('react').Context<import('@tanstack/react-form').AnyFieldApi>, formContext: import('react').Context<import('@tanstack/react-form').AnyFormApi>;
5
+ export { fieldContext, formContext };
6
+ /**
7
+ * Custom hook to handle disabled state for form fields
8
+ * @param {boolean} disabled - The disabled prop passed to the component
9
+ * @returns The field context with disabled state properly managed
10
+ */
11
+ export declare function useFieldContext<T>({ disabled }: {
12
+ disabled?: boolean;
13
+ }): import('@tanstack/react-form').FieldApi<any, string, T, any, any, any, any, any, any, any, any, any, any, any, any, any, any, any, any>;
@@ -1,2 +1,2 @@
1
- import{createFormHookContexts as o}from"@tanstack/react-form";const{fieldContext:e,formContext:r,useFieldContext:n}=o();export{e as fieldContext,r as formContext,n as useFieldContext};
1
+ import{createFormHookContexts as n}from"@tanstack/react-form";import{useEffect as r}from"react";const{fieldContext:x,formContext:m,useFieldContext:f}=n();function u({disabled:e}){const t=f();return r(()=>{t.setMeta(o=>({...o,disabled:!!e}))},[e,t]),t}export{x as fieldContext,m as formContext,u as useFieldContext};
2
2
  //# sourceMappingURL=form-context.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"form-context.js","sources":["../../lib/utilities/form-context.tsx"],"sourcesContent":["import { createFormHookContexts } from '@tanstack/react-form';\n\n/**\n * useFieldContext is used in custom components\n */\nexport const { fieldContext, formContext, useFieldContext } = createFormHookContexts();\n"],"names":["fieldContext","formContext","useFieldContext","createFormHookContexts"],"mappings":"8DAKO,KAAM,CAAE,aAAAA,EAAc,YAAAC,EAAa,gBAAAC,CAAA,EAAoBC,EAAA"}
1
+ {"version":3,"file":"form-context.js","sources":["../../lib/utilities/form-context.tsx"],"sourcesContent":["import { createFormHookContexts } from '@tanstack/react-form';\nimport { useEffect } from 'react';\n\n/**\n * useFieldContext is used in custom components\n */\nconst { fieldContext, formContext, useFieldContext: _useFieldContext } = createFormHookContexts();\n\nexport { fieldContext, formContext };\n/**\n * Custom hook to handle disabled state for form fields\n * @param {boolean} disabled - The disabled prop passed to the component\n * @returns The field context with disabled state properly managed\n */\nexport function useFieldContext<T>({ disabled }: { disabled?: boolean }) {\n const field = _useFieldContext<T>();\n\n useEffect(() => {\n field.setMeta(meta => ({\n ...meta,\n disabled: !!disabled,\n }));\n }, [disabled, field]);\n\n return field;\n}\n"],"names":["fieldContext","formContext","_useFieldContext","createFormHookContexts","useFieldContext","disabled","field","useEffect","meta"],"mappings":"gGAMA,KAAM,CAAE,aAAAA,EAAc,YAAAC,EAAa,gBAAiBC,CAAA,EAAqBC,EAAA,EAQlE,SAASC,EAAmB,CAAE,SAAAC,GAAoC,CACrE,MAAMC,EAAQJ,EAAA,EAEd,OAAAK,EAAU,IAAM,CACZD,EAAM,QAAQE,IAAS,CACnB,GAAGA,EACH,SAAU,CAAC,CAACH,CAAA,EACd,CACN,EAAG,CAACA,EAAUC,CAAK,CAAC,EAEbA,CACX"}
@@ -1,2 +1,2 @@
1
- import{createFormHook as o}from"@tanstack/react-form";import{Button as m}from"../components/button.js";import{TfCheckbox as r}from"../components/checkbox.js";import{TfMultiSelect as t}from"../components/multi-select.js";import{TfNumberField as i}from"../components/numberfield.js";import{TfSingleSelect as p}from"../components/select.js";import{TfTextField as e}from"../components/textfield.js";import{formContext as f,fieldContext as n}from"./form-context.js";import"react/jsx-runtime";import"class-variance-authority";import"react-aria-components";import"./theme.js";import"clsx";import"../components/loader.js";import"../components/icons.js";import"react";import"../components/field.js";import"./form.js";import"../components/menu.js";import"../components/list-box.js";import"../components/popover.js";const{useAppForm:q}=o({fieldComponents:{TfTextField:e,TfNumberField:i,TfMultiSelect:t,TfSingleSelect:p,TfCheckbox:r},formComponents:{Button:m},fieldContext:n,formContext:f});export{q as useAppForm};
1
+ import{createFormHook as o}from"@tanstack/react-form";import{Button as m}from"../components/button.js";import{TfCheckbox as r}from"../components/checkbox.js";import{TfMultiSelect as t}from"../components/multi-select.js";import{TfNumberField as i}from"../components/numberfield.js";import{TfSingleSelect as p}from"../components/select.js";import{TfTextField as e}from"../components/textfield.js";import{formContext as f,fieldContext as n}from"./form-context.js";import"react/jsx-runtime";import"class-variance-authority";import"react-aria-components";import"./theme.js";import"clsx";import"../components/loader.js";import"../components/icons.js";import"react";import"../components/field.js";import"../components/menu.js";import"../components/list-box.js";import"./form.js";import"../components/popover.js";const{useAppForm:q}=o({fieldComponents:{TfTextField:e,TfNumberField:i,TfMultiSelect:t,TfSingleSelect:p,TfCheckbox:r},formComponents:{Button:m},fieldContext:n,formContext:f});export{q as useAppForm};
2
2
  //# sourceMappingURL=form-hook.js.map
@@ -1,13 +1,4 @@
1
1
  import { FieldApi, FormApi } from '@tanstack/react-form';
2
- type FieldContextProps = {
3
- disabled?: boolean;
4
- };
5
- /**
6
- * Custom hook to handle disabled state for form fields
7
- * @param {boolean} disabled - The disabled prop passed to the component
8
- * @returns The field context with disabled state properly managed
9
- */
10
- export declare function useTfFieldContext<T>({ disabled }: FieldContextProps): FieldApi<any, string, T, any, any, any, any, any, any, any, any, any, any, any, any, any, any, any, any>;
11
2
  /** Utility type to simplify FormApi usage */
12
3
  export type AppFormApi<TValues> = FormApi<TValues, any, any, any, any, any, any, any, any, any>;
13
4
  /**
@@ -22,4 +13,3 @@ export declare function tfOnSubmit<TValues>(onSubmit: ({ values, formApi }: {
22
13
  formApi: AppFormApi<TValues>;
23
14
  }) => Promise<any>;
24
15
  export declare function getFieldErrorMessage(field: FieldApi<any, any, any, any, any, any, any, any, any, any, any, any, any, any, any, any, any, any, any>): string;
25
- export {};
@@ -1,2 +1,2 @@
1
- import o from"react";import{useFieldContext as r}from"./form-context.js";import"@tanstack/react-form";function l({disabled:e}){const t=r();return o.useEffect(()=>{t.setMeta(n=>({...n,disabled:!!e}))},[e,t]),t}function d(e){return async({formApi:t})=>{const n=i(t.state.values,t);await e({values:n,formApi:t})}}function i(e,t){const n={};for(const s in e)t.getFieldMeta(s)?.disabled||(n[s]=e[s]);return n}function m(e){return e?.state.meta.errors.map(t=>t?.message).join(",")}export{m as getFieldErrorMessage,d as tfOnSubmit,l as useTfFieldContext};
1
+ function i(t){return async({formApi:e})=>{const n=a(e.state.values,e);await t({values:n,formApi:e})}}function a(t,e){const n={};for(const s in t)e.getFieldMeta(s)?.disabled||(n[s]=t[s]);return n}function o(t){return t?.state.meta.errors.map(e=>e?.message).join(",")}export{o as getFieldErrorMessage,i as tfOnSubmit};
2
2
  //# sourceMappingURL=form.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"form.js","sources":["../../lib/utilities/form.tsx"],"sourcesContent":["import { type AnyFieldMeta, type FieldApi, type FormApi } from '@tanstack/react-form';\nimport React from 'react';\nimport { useFieldContext } from './form-context';\n\ntype FieldContextProps = {\n disabled?: boolean;\n};\n\n/**\n * Custom hook to handle disabled state for form fields\n * @param {boolean} disabled - The disabled prop passed to the component\n * @returns The field context with disabled state properly managed\n */\nexport function useTfFieldContext<T>({ disabled }: FieldContextProps) {\n const field = useFieldContext<T>();\n\n React.useEffect(() => {\n field.setMeta(meta => ({\n ...meta,\n disabled: !!disabled,\n }));\n }, [disabled, field]);\n\n return field;\n}\n\n/** Utility type to simplify FormApi usage */\nexport type AppFormApi<TValues> = FormApi<TValues, any, any, any, any, any, any, any, any, any>;\n\n/**\n * Utility function to submit a form with a handler that receives the values and the formApi.\n * @param onSubmit - The handler function to call with the values and the formApi.\n * @returns A function that can be used to submit the form. It will filter out disabled fields from the values.\n */\nexport function tfOnSubmit<TValues>(\n onSubmit: ({ values, formApi }: { values: TValues; formApi: AppFormApi<TValues> }) => Promise<any> | any\n) {\n return async ({ formApi }: { formApi: AppFormApi<TValues> }): Promise<any> => {\n const values = pickEnabledFields(formApi.state.values, formApi);\n\n await onSubmit({ values, formApi });\n };\n}\nfunction pickEnabledFields<TValues>(rawValues: TValues, formApi: AppFormApi<TValues>): TValues {\n const result: TValues = {} as TValues;\n\n //TODO: Nested objects are not supported yet\n for (const key in rawValues) {\n const meta = formApi.getFieldMeta(key) as AnyFieldMeta & {\n disabled?: boolean;\n };\n if (!meta?.disabled) {\n result[key] = rawValues[key];\n }\n }\n\n return result;\n}\n\nexport function getFieldErrorMessage(\n field: FieldApi<any, any, any, any, any, any, any, any, any, any, any, any, any, any, any, any, any, any, any>\n): string {\n return field?.state.meta.errors.map(e => e?.message).join(',');\n}\n"],"names":["useTfFieldContext","disabled","field","useFieldContext","React","meta","tfOnSubmit","onSubmit","formApi","values","pickEnabledFields","rawValues","result","key","getFieldErrorMessage","e"],"mappings":"sGAaO,SAASA,EAAqB,CAAE,SAAAC,GAA+B,CAClE,MAAMC,EAAQC,EAAA,EAEd,OAAAC,EAAM,UAAU,IAAM,CAClBF,EAAM,QAAQG,IAAS,CACnB,GAAGA,EACH,SAAU,CAAC,CAACJ,CAAA,EACd,CACN,EAAG,CAACA,EAAUC,CAAK,CAAC,EAEbA,CACX,CAUO,SAASI,EACZC,EACF,CACE,MAAO,OAAO,CAAE,QAAAC,KAA8D,CAC1E,MAAMC,EAASC,EAAkBF,EAAQ,MAAM,OAAQA,CAAO,EAE9D,MAAMD,EAAS,CAAE,OAAAE,EAAQ,QAAAD,EAAS,CACtC,CACJ,CACA,SAASE,EAA2BC,EAAoBH,EAAuC,CAC3F,MAAMI,EAAkB,CAAA,EAGxB,UAAWC,KAAOF,EACDH,EAAQ,aAAaK,CAAG,GAG1B,WACPD,EAAOC,CAAG,EAAIF,EAAUE,CAAG,GAInC,OAAOD,CACX,CAEO,SAASE,EACZZ,EACM,CACN,OAAOA,GAAO,MAAM,KAAK,OAAO,OAASa,GAAG,OAAO,EAAE,KAAK,GAAG,CACjE"}
1
+ {"version":3,"file":"form.js","sources":["../../lib/utilities/form.tsx"],"sourcesContent":["import { type AnyFieldMeta, type FieldApi, type FormApi } from '@tanstack/react-form';\n\n/** Utility type to simplify FormApi usage */\nexport type AppFormApi<TValues> = FormApi<TValues, any, any, any, any, any, any, any, any, any>;\n\n/**\n * Utility function to submit a form with a handler that receives the values and the formApi.\n * @param onSubmit - The handler function to call with the values and the formApi.\n * @returns A function that can be used to submit the form. It will filter out disabled fields from the values.\n */\nexport function tfOnSubmit<TValues>(\n onSubmit: ({ values, formApi }: { values: TValues; formApi: AppFormApi<TValues> }) => Promise<any> | any\n) {\n return async ({ formApi }: { formApi: AppFormApi<TValues> }): Promise<any> => {\n const values = pickEnabledFields(formApi.state.values, formApi);\n\n await onSubmit({ values, formApi });\n };\n}\nfunction pickEnabledFields<TValues>(rawValues: TValues, formApi: AppFormApi<TValues>): TValues {\n const result: TValues = {} as TValues;\n\n //TODO: Nested objects are not supported yet\n for (const key in rawValues) {\n const meta = formApi.getFieldMeta(key) as AnyFieldMeta & {\n disabled?: boolean;\n };\n if (!meta?.disabled) {\n result[key] = rawValues[key];\n }\n }\n\n return result;\n}\n\nexport function getFieldErrorMessage(\n field: FieldApi<any, any, any, any, any, any, any, any, any, any, any, any, any, any, any, any, any, any, any>\n): string {\n return field?.state.meta.errors.map(e => e?.message).join(',');\n}\n"],"names":["tfOnSubmit","onSubmit","formApi","values","pickEnabledFields","rawValues","result","key","getFieldErrorMessage","field"],"mappings":"AAUO,SAASA,EACZC,EACF,CACE,MAAO,OAAO,CAAE,QAAAC,KAA8D,CAC1E,MAAMC,EAASC,EAAkBF,EAAQ,MAAM,OAAQA,CAAO,EAE9D,MAAMD,EAAS,CAAE,OAAAE,EAAQ,QAAAD,EAAS,CACtC,CACJ,CACA,SAASE,EAA2BC,EAAoBH,EAAuC,CAC3F,MAAMI,EAAkB,CAAA,EAGxB,UAAWC,KAAOF,EACDH,EAAQ,aAAaK,CAAG,GAG1B,WACPD,EAAOC,CAAG,EAAIF,EAAUE,CAAG,GAInC,OAAOD,CACX,CAEO,SAASE,EACZC,EACM,CACN,OAAOA,GAAO,MAAM,KAAK,OAAO,OAAS,GAAG,OAAO,EAAE,KAAK,GAAG,CACjE"}
@@ -1,4 +1,4 @@
1
- import { components, operations } from '@cryptlex/web-api-types';
1
+ import { components, operations } from '@cryptlex/web-api-types/develop';
2
2
  export type ApiSchema<T extends keyof components['schemas']> = components['schemas'][T];
3
3
  export type ApiQuery<T extends keyof operations> = NonNullable<operations[T]['parameters']['query']>;
4
4
  export type ApiFilter<T extends keyof operations> = Omit<ApiQuery<T>, 'page' | 'limit' | 'sort' | 'search'>;
@@ -20,6 +20,6 @@ export type CtxResourceName = (typeof CTX_RESOURCES)[number];
20
20
  * Format multiple license parameters (expired, suspended, revoked) into a single status
21
21
  */
22
22
  export declare function getLicenseStatus(license: any): string;
23
- export declare const ALL_OS: {
24
- [key: string]: string;
25
- };
23
+ type OsType = ApiSchema<'ActivationCreateRequestModel'>['os'];
24
+ export declare const ALL_OS: Record<OsType, string>;
25
+ export {};
@@ -1 +1 @@
1
- {"version":3,"file":"resources.js","sources":["../../lib/utilities/resources.tsx"],"sourcesContent":["import type { components, operations } from '@cryptlex/web-api-types';\nimport { createContext, use } from 'react';\nimport { toTitleCase } from './string';\n\nexport type ApiSchema<T extends keyof components['schemas']> = components['schemas'][T];\nexport type ApiQuery<T extends keyof operations> = NonNullable<operations[T]['parameters']['query']>;\nexport type ApiFilter<T extends keyof operations> = Omit<ApiQuery<T>, 'page' | 'limit' | 'sort' | 'search'>;\nexport type ApiFilters<T extends keyof operations> = NonNullable<ApiFilter<T>>;\nexport type CtxPortals = 'customer-portal' | 'system-portal' | 'reseller-portal' | 'admin-portal';\n// Display names specific to customer and reseller portal\nconst OTHER_PORTALS_DISPLAY_NAME: Record<string, string> = {\n 'product.displayName': 'Product',\n // TanStack Table converts . -> _ TODO\n product_displayName: 'Product',\n};\n\n/** Resource Name should ALWAYS be in singular form */\nexport const RESOURCE_NAMES = [\n 'access-token',\n 'account',\n 'activation',\n 'activation-log',\n 'admin-role',\n 'audit-log',\n 'automated-email',\n 'automated-email-event-log',\n 'card',\n 'feature-flag',\n 'invoice',\n 'license',\n 'license-template',\n 'maintenance-policy',\n 'organization',\n 'plan',\n 'product',\n 'product-version',\n 'profile',\n 'release',\n 'release-channel',\n 'release-file',\n 'release-platform',\n 'report',\n 'role',\n 'role-claim',\n 'saml-configuration',\n 'segment',\n 'sending-domain',\n 'setting',\n 'tag',\n 'team-member',\n 'trial',\n 'trial-policy',\n 'user',\n 'user-group',\n 'webhook',\n 'webhook-event-log',\n 'webhook-trigger',\n 'reseller',\n 'oidc-configuration',\n 'organization-claim',\n 'reseller-claim',\n] as const;\nexport type ResourceName = (typeof RESOURCE_NAMES)[number];\nexport const RESOURCE_DEFINITIONS: Record<ResourceName, string> = {\n account: 'Your organization account.',\n product: 'Products are the software products you want to license',\n license:\n 'Licenses represent a purchase of your software. These can be linked to customers, and the license key is required to use the product.',\n 'access-token': 'Access Tokens are used to authenticate your API requests.',\n activation: 'Activations, also known as devices/machines/seats are the devices consuming licenses.',\n 'activation-log': 'Activation Log is a log entry of activation/deactivation of a particular license.',\n trial: 'Trial/Trial Activation is a device that has activated a trial of your product.',\n 'audit-log': 'Audit logs contain all the changes made to your account.',\n 'automated-email': 'Automated Email allow you to send marketing emails based on events on the linked product.',\n 'automated-email-event-log':\n 'Automated email event log is the log of all the automated email events for your product.',\n card: 'The payment card for your account.',\n 'feature-flag': 'Feature flags define features that make up tiers for your products.',\n invoice: '',\n 'license-template':\n 'License templates are a blueprint for the licenses you create for your customers and prevent repetition when creating licenses.',\n 'maintenance-policy': 'Maintenance policies represent support contracts and can be linked to licenses.',\n plan: '',\n 'product-version': 'Product Versions are sets of Feature Flags that define the tiers of your products.',\n 'release-channel': 'Release channel is the release channel for your product.',\n 'release-file': 'Release files are files within your created releases.',\n 'release-platform':\n 'Release Platforms differentiate the target platform for your release. Common platforms include \"Windows\", \"macOS\", and \"Linux\".',\n release: 'Releases help you to manage different versions of your app, and secure distribute it to licensed users.',\n report: 'Analytics data for your account',\n 'role-claim': '',\n role: 'Roles define permissions for your team.',\n 'saml-configuration': '',\n segment: 'Sets of filters that can be saved to filter resources.',\n 'trial-policy': 'Trial policies are templates for creating trials for your products.',\n 'webhook-event-log': 'Webhook Event Logs are logs of events that have occured on webhooks.',\n 'webhook-trigger': '',\n webhook: 'Webhooks are HTTP callbacks which are triggered by specific events.',\n organization: '',\n profile: '',\n setting: '',\n tag: 'Tags allow you to manage your licenses and customers on the dashboard.',\n 'team-member': 'Team members can access the account based on their roles.',\n user: 'A user refers to your customer whom you want to license your product.',\n 'sending-domain': 'Allows Cryptlex to send emails on your behalf using your From Email address',\n 'admin-role': 'Roles that have type admin',\n 'user-group': 'Groups of users that you can assign licenses to.',\n reseller: 'Resellers allow you to delegate user management to third parties or partners',\n 'oidc-configuration': '',\n 'organization-claim': '',\n 'reseller-claim': '',\n};\n\nconst RESOURCE_DISPLAY_NAMES: Record<string, string> = {\n id: 'ID',\n createdAt: 'Creation Date',\n scopes: 'Permissions',\n updatedAt: 'Last Updated',\n expiresAt: 'Expiration Date',\n lastSeenAt: 'Last Seen',\n os: 'OS',\n osVersion: 'OS Version',\n key: 'License Key',\n vmName: 'VM Name',\n container: 'Container',\n allowedIpRange: 'Allowed IP Range',\n allowedIpRanges: 'Allowed IP Ranges',\n allowedIpAddresses: 'Allowed IP Addresses',\n disallowedIpAddresses: 'Disallowed IP Addresses',\n allowVmActivation: 'Allow VM Activation',\n disableGeoLocation: 'Disable Geolocation',\n 'user.id': 'User ID',\n userId: 'User',\n productId: 'Product',\n downloads: 'Total Downloads',\n claims: 'Permissions',\n googleSsoEnabled: 'Google Login Enabled',\n lastAttemptedAt: 'Last Attempt Date',\n url: 'URL',\n 'trialPolicy.name': 'Trial Policy Name',\n 'licensePolicy.name': 'License Template Name',\n licensePolicy: 'License Template',\n eventLog: 'Audit Log',\n cc: 'CC Recepients',\n bcc: 'BCC Recepients',\n ipAddress: 'IP Address',\n resellerId: 'Reseller',\n productVersionId: 'Product Version',\n releaseId: 'Release',\n maintenancePolicyId: 'Maintenance Policy',\n webhookId: 'Webhook',\n automatedEmailId: 'Automated Email',\n 'location.countryName': 'Country',\n 'location.ipAddress': 'IP Address',\n 'location.countryCode': 'Country',\n organizationId: 'Organization',\n 'address.country': 'Country',\n 'address.addressLine1': 'Address Line 1',\n 'address.addressLine2': 'Address Line 2',\n responseStatusCode: 'HTTP Status Code',\n resourceId: 'Resource ID',\n Sso: 'SAML SSO 2.0',\n 'reseller.name': 'Reseller',\n sendingDomain: 'Email Sending Domain',\n};\n\nfunction getResourceDisplayName(resourceName: string, portal: CtxPortals) {\n if (portal !== 'admin-portal' && resourceName in OTHER_PORTALS_DISPLAY_NAME) {\n return OTHER_PORTALS_DISPLAY_NAME[resourceName];\n } else if (resourceName in RESOURCE_DISPLAY_NAMES) {\n return RESOURCE_DISPLAY_NAMES[resourceName];\n } else {\n return toTitleCase(resourceName);\n }\n}\n\nconst ProjectContext = createContext<CtxPortals>('admin-portal');\n\nexport function ProjectProvider({ projectName, children }: { projectName: CtxPortals; children: React.ReactNode }) {\n return <ProjectContext.Provider value={projectName}>{children}</ProjectContext.Provider>;\n}\n\nexport function useProjectName(): CtxPortals {\n const projectName = use(ProjectContext);\n return projectName;\n}\n\n// TODO, create story with complete map of resource -> formatter output\nexport function useResourceFormatter(): (resourceName: string) => string {\n const portal = useProjectName();\n return (resourceName: string) => getResourceDisplayName(resourceName, portal);\n}\n\nexport const CTX_RESOURCES = [\n 'account',\n 'activation',\n 'automatedEmail',\n 'billingAddress',\n 'entitlementSet',\n 'feature',\n 'featureEntitlement',\n 'featureFlag',\n 'license',\n 'licenseTemplate',\n 'maintenancePolicy',\n 'oidcConfiguration',\n 'oidcRoleMapping',\n 'organization',\n 'paymentMethod',\n 'personalAccessToken',\n 'plan',\n 'product',\n 'productVersion',\n 'release',\n 'releaseChannel',\n 'releaseFile',\n 'releasePlatform',\n 'reseller',\n 'role',\n 'samlConfiguration',\n 'segment',\n 'sendingDomain',\n 'tag',\n 'trialActivation',\n 'trialPolicy',\n 'user',\n 'userGroup',\n 'webhook',\n] as const;\n\nexport type CtxResourceName = (typeof CTX_RESOURCES)[number];\n\n/**\n * Format multiple license parameters (expired, suspended, revoked) into a single status\n */\nexport function getLicenseStatus(license: any): string {\n const licenseExpired = license.expiresAt && new Date(license.expiresAt) < new Date();\n // Status Column\n switch (true) {\n case license.revoked && license.suspended && licenseExpired:\n return 'Revoked, Suspended, Expired';\n case license.revoked && license.suspended:\n return 'Revoked, Suspended';\n case license.revoked && licenseExpired:\n return 'Revoked, Expired';\n case license.suspended && licenseExpired:\n return 'Suspended, Expired';\n case license.suspended:\n return 'Suspended';\n case license.revoked:\n return 'Revoked';\n case licenseExpired:\n return 'Expired';\n default:\n return 'Active';\n }\n}\n// TODO, use ApiSchema\nexport const ALL_OS: { [key: string]: string } = {\n windows: 'Windows',\n macos: 'macOS',\n linux: 'Linux',\n ios: 'iOS',\n android: 'Android',\n};\n"],"names":["OTHER_PORTALS_DISPLAY_NAME","RESOURCE_NAMES","RESOURCE_DEFINITIONS","RESOURCE_DISPLAY_NAMES","getResourceDisplayName","resourceName","portal","toTitleCase","ProjectContext","createContext","ProjectProvider","projectName","children","useProjectName","use","useResourceFormatter","CTX_RESOURCES","getLicenseStatus","license","licenseExpired","ALL_OS"],"mappings":"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"}
1
+ {"version":3,"file":"resources.js","sources":["../../lib/utilities/resources.tsx"],"sourcesContent":["import type { components, operations } from '@cryptlex/web-api-types/develop';\nimport { createContext, use } from 'react';\nimport { toTitleCase } from './string';\n\nexport type ApiSchema<T extends keyof components['schemas']> = components['schemas'][T];\nexport type ApiQuery<T extends keyof operations> = NonNullable<operations[T]['parameters']['query']>;\nexport type ApiFilter<T extends keyof operations> = Omit<ApiQuery<T>, 'page' | 'limit' | 'sort' | 'search'>;\nexport type ApiFilters<T extends keyof operations> = NonNullable<ApiFilter<T>>;\nexport type CtxPortals = 'customer-portal' | 'system-portal' | 'reseller-portal' | 'admin-portal';\n// Display names specific to customer and reseller portal\nconst OTHER_PORTALS_DISPLAY_NAME: Record<string, string> = {\n 'product.displayName': 'Product',\n // TanStack Table converts . -> _ TODO\n product_displayName: 'Product',\n};\n\n/** Resource Name should ALWAYS be in singular form */\nexport const RESOURCE_NAMES = [\n 'access-token',\n 'account',\n 'activation',\n 'activation-log',\n 'admin-role',\n 'audit-log',\n 'automated-email',\n 'automated-email-event-log',\n 'card',\n 'feature-flag',\n 'invoice',\n 'license',\n 'license-template',\n 'maintenance-policy',\n 'organization',\n 'plan',\n 'product',\n 'product-version',\n 'profile',\n 'release',\n 'release-channel',\n 'release-file',\n 'release-platform',\n 'report',\n 'role',\n 'role-claim',\n 'saml-configuration',\n 'segment',\n 'sending-domain',\n 'setting',\n 'tag',\n 'team-member',\n 'trial',\n 'trial-policy',\n 'user',\n 'user-group',\n 'webhook',\n 'webhook-event-log',\n 'webhook-trigger',\n 'reseller',\n 'oidc-configuration',\n 'organization-claim',\n 'reseller-claim',\n] as const;\nexport type ResourceName = (typeof RESOURCE_NAMES)[number];\nexport const RESOURCE_DEFINITIONS: Record<ResourceName, string> = {\n account: 'Your organization account.',\n product: 'Products are the software products you want to license',\n license:\n 'Licenses represent a purchase of your software. These can be linked to customers, and the license key is required to use the product.',\n 'access-token': 'Access Tokens are used to authenticate your API requests.',\n activation: 'Activations, also known as devices/machines/seats are the devices consuming licenses.',\n 'activation-log': 'Activation Log is a log entry of activation/deactivation of a particular license.',\n trial: 'Trial/Trial Activation is a device that has activated a trial of your product.',\n 'audit-log': 'Audit logs contain all the changes made to your account.',\n 'automated-email': 'Automated Email allow you to send marketing emails based on events on the linked product.',\n 'automated-email-event-log':\n 'Automated email event log is the log of all the automated email events for your product.',\n card: 'The payment card for your account.',\n 'feature-flag': 'Feature flags define features that make up tiers for your products.',\n invoice: '',\n 'license-template':\n 'License templates are a blueprint for the licenses you create for your customers and prevent repetition when creating licenses.',\n 'maintenance-policy': 'Maintenance policies represent support contracts and can be linked to licenses.',\n plan: '',\n 'product-version': 'Product Versions are sets of Feature Flags that define the tiers of your products.',\n 'release-channel': 'Release channel is the release channel for your product.',\n 'release-file': 'Release files are files within your created releases.',\n 'release-platform':\n 'Release Platforms differentiate the target platform for your release. Common platforms include \"Windows\", \"macOS\", and \"Linux\".',\n release: 'Releases help you to manage different versions of your app, and secure distribute it to licensed users.',\n report: 'Analytics data for your account',\n 'role-claim': '',\n role: 'Roles define permissions for your team.',\n 'saml-configuration': '',\n segment: 'Sets of filters that can be saved to filter resources.',\n 'trial-policy': 'Trial policies are templates for creating trials for your products.',\n 'webhook-event-log': 'Webhook Event Logs are logs of events that have occured on webhooks.',\n 'webhook-trigger': '',\n webhook: 'Webhooks are HTTP callbacks which are triggered by specific events.',\n organization: '',\n profile: '',\n setting: '',\n tag: 'Tags allow you to manage your licenses and customers on the dashboard.',\n 'team-member': 'Team members can access the account based on their roles.',\n user: 'A user refers to your customer whom you want to license your product.',\n 'sending-domain': 'Allows Cryptlex to send emails on your behalf using your From Email address',\n 'admin-role': 'Roles that have type admin',\n 'user-group': 'Groups of users that you can assign licenses to.',\n reseller: 'Resellers allow you to delegate user management to third parties or partners',\n 'oidc-configuration': '',\n 'organization-claim': '',\n 'reseller-claim': '',\n};\n\nconst RESOURCE_DISPLAY_NAMES: Record<string, string> = {\n id: 'ID',\n createdAt: 'Creation Date',\n scopes: 'Permissions',\n updatedAt: 'Last Updated',\n expiresAt: 'Expiration Date',\n lastSeenAt: 'Last Seen',\n os: 'OS',\n osVersion: 'OS Version',\n key: 'License Key',\n vmName: 'VM Name',\n container: 'Container',\n allowedIpRange: 'Allowed IP Range',\n allowedIpRanges: 'Allowed IP Ranges',\n allowedIpAddresses: 'Allowed IP Addresses',\n disallowedIpAddresses: 'Disallowed IP Addresses',\n allowVmActivation: 'Allow VM Activation',\n disableGeoLocation: 'Disable Geolocation',\n 'user.id': 'User ID',\n userId: 'User',\n productId: 'Product',\n downloads: 'Total Downloads',\n claims: 'Permissions',\n googleSsoEnabled: 'Google Login Enabled',\n lastAttemptedAt: 'Last Attempt Date',\n url: 'URL',\n 'trialPolicy.name': 'Trial Policy Name',\n 'licensePolicy.name': 'License Template Name',\n licensePolicy: 'License Template',\n eventLog: 'Audit Log',\n cc: 'CC Recepients',\n bcc: 'BCC Recepients',\n ipAddress: 'IP Address',\n resellerId: 'Reseller',\n productVersionId: 'Product Version',\n releaseId: 'Release',\n maintenancePolicyId: 'Maintenance Policy',\n webhookId: 'Webhook',\n automatedEmailId: 'Automated Email',\n 'location.countryName': 'Country',\n 'location.ipAddress': 'IP Address',\n 'location.countryCode': 'Country',\n organizationId: 'Organization',\n 'address.country': 'Country',\n 'address.addressLine1': 'Address Line 1',\n 'address.addressLine2': 'Address Line 2',\n responseStatusCode: 'HTTP Status Code',\n resourceId: 'Resource ID',\n Sso: 'SAML SSO 2.0',\n 'reseller.name': 'Reseller',\n sendingDomain: 'Email Sending Domain',\n};\n\nfunction getResourceDisplayName(resourceName: string, portal: CtxPortals) {\n if (portal !== 'admin-portal' && resourceName in OTHER_PORTALS_DISPLAY_NAME) {\n return OTHER_PORTALS_DISPLAY_NAME[resourceName];\n } else if (resourceName in RESOURCE_DISPLAY_NAMES) {\n return RESOURCE_DISPLAY_NAMES[resourceName];\n } else {\n return toTitleCase(resourceName);\n }\n}\n\nconst ProjectContext = createContext<CtxPortals>('admin-portal');\n\nexport function ProjectProvider({ projectName, children }: { projectName: CtxPortals; children: React.ReactNode }) {\n return <ProjectContext.Provider value={projectName}>{children}</ProjectContext.Provider>;\n}\n\nexport function useProjectName(): CtxPortals {\n const projectName = use(ProjectContext);\n return projectName;\n}\n\n// TODO, create story with complete map of resource -> formatter output\nexport function useResourceFormatter(): (resourceName: string) => string {\n const portal = useProjectName();\n return (resourceName: string) => getResourceDisplayName(resourceName, portal);\n}\n\nexport const CTX_RESOURCES = [\n 'account',\n 'activation',\n 'automatedEmail',\n 'billingAddress',\n 'entitlementSet',\n 'feature',\n 'featureEntitlement',\n 'featureFlag',\n 'license',\n 'licenseTemplate',\n 'maintenancePolicy',\n 'oidcConfiguration',\n 'oidcRoleMapping',\n 'organization',\n 'paymentMethod',\n 'personalAccessToken',\n 'plan',\n 'product',\n 'productVersion',\n 'release',\n 'releaseChannel',\n 'releaseFile',\n 'releasePlatform',\n 'reseller',\n 'role',\n 'samlConfiguration',\n 'segment',\n 'sendingDomain',\n 'tag',\n 'trialActivation',\n 'trialPolicy',\n 'user',\n 'userGroup',\n 'webhook',\n] as const;\n\nexport type CtxResourceName = (typeof CTX_RESOURCES)[number];\n\n/**\n * Format multiple license parameters (expired, suspended, revoked) into a single status\n */\nexport function getLicenseStatus(license: any): string {\n const licenseExpired = license.expiresAt && new Date(license.expiresAt) < new Date();\n // Status Column\n switch (true) {\n case license.revoked && license.suspended && licenseExpired:\n return 'Revoked, Suspended, Expired';\n case license.revoked && license.suspended:\n return 'Revoked, Suspended';\n case license.revoked && licenseExpired:\n return 'Revoked, Expired';\n case license.suspended && licenseExpired:\n return 'Suspended, Expired';\n case license.suspended:\n return 'Suspended';\n case license.revoked:\n return 'Revoked';\n case licenseExpired:\n return 'Expired';\n default:\n return 'Active';\n }\n}\ntype OsType = ApiSchema<'ActivationCreateRequestModel'>['os'];\nexport const ALL_OS: Record<OsType, string> = {\n windows: 'Windows',\n macos: 'macOS',\n linux: 'Linux',\n ios: 'iOS',\n android: 'Android',\n};\n"],"names":["OTHER_PORTALS_DISPLAY_NAME","RESOURCE_NAMES","RESOURCE_DEFINITIONS","RESOURCE_DISPLAY_NAMES","getResourceDisplayName","resourceName","portal","toTitleCase","ProjectContext","createContext","ProjectProvider","projectName","children","useProjectName","use","useResourceFormatter","CTX_RESOURCES","getLicenseStatus","license","licenseExpired","ALL_OS"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cryptlex/web-components",
3
- "version": "6.6.6-alpha08",
3
+ "version": "6.6.6-alpha10",
4
4
  "description": "React component library for Cryptlex web applications",
5
5
  "author": "Cryptlex",
6
6
  "type": "module",
@@ -45,7 +45,7 @@
45
45
  "*.{ts,tsx,css,scss,json}": "prettier --write"
46
46
  },
47
47
  "peerDependencies": {
48
- "@cryptlex/web-api-types": "1.45.0",
48
+ "@cryptlex/web-api-types": "2.0.0",
49
49
  "@dnd-kit/core": "6.3.1",
50
50
  "@dnd-kit/sortable": "10.0.0",
51
51
  "@dnd-kit/utilities": "3.2.2",