@nexia/sdk 0.8.12 → 0.8.13

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -69,3 +69,76 @@ an SDK-only update does not install server routes.
69
69
  Test both a successful call and a denied call through an actual development
70
70
  frame or installed App transport. For invitations, use a test mail sink; for
71
71
  imports, verify the terminal result as well as the initial 202 response.
72
+
73
+ ## Search and select dialogs
74
+
75
+ `NxLookupDialog` from `@nexia/sdk/host` presents an owner-authorized server page
76
+ with search, filter slots, sorting and single/multiple selection. Supply
77
+ `NxLookupRow` values with stable IDs, readable labels and column cells. The
78
+ component retains draft selections across page/query changes; `onApply` returns
79
+ the complete selected rows, while `onClose` cancels without changing `value`.
80
+ An empty selection is returned as `[]`; the caller decides whether this means
81
+ no selection or an unrestricted list filter. Select-all applies only to enabled
82
+ rows on the current page, never all matching records on the server.
83
+
84
+ Keep API calls, debounce/cancellation, permissions, filter semantics and page
85
+ reset in the owner component. Set `loading` while a page/query is changing to
86
+ prevent selection from stale results. Supply `error` and `onRetry` on failure.
87
+ `filters` holds frequent controls and `advancedFilters` the collapsible details;
88
+ `activeFilterCount` keeps active advanced conditions visible when collapsed.
89
+ `maxSelection` bounds a multiple-selection workflow. The host provides localized
90
+ controls, modal focus/dismissal, and a selected-items view. Use the matching Core
91
+ host implementation before adopting this SDK export. Existing comboboxes remain
92
+ appropriate for small option lists; this does not replace every selector.
93
+
94
+ For a single choice without checkboxes/radios or an Apply step, set
95
+ `multiple={false} applyOnSelect`. Clicking a row (or activating its first-cell
96
+ button with Enter/Space) calls `onApply([row])`, then `onClose()` immediately.
97
+ Disabled/loading rows cannot apply. Cancel/close still leaves the value intact.
98
+ Omit `applyOnSelect` to keep single-selection radio buttons and explicit Apply;
99
+ in multiple-selection mode it is ignored so checking a row never closes the dialog.
100
+
101
+ ## Dedicated lookup fields
102
+
103
+ Use `NxLookupField` from `@nexia/sdk/host` for a field that opens a record lookup.
104
+ `NxCombobox` now owns only popover list selection. The earlier draft
105
+ `NxCombobox presentation="dialog"` API and its lookup-only props are removed.
106
+ Adopt the matching SDK and Core host together; this draft does not declare a
107
+ released minimum version.
108
+
109
+ `NxLookupField` displays the applied value and opens the shared `NxLookupDialog`.
110
+ It supports typed string/number values, single/multiple selection, create
111
+ continuation, refresh, and optional selected-item chips. Single selection applies
112
+ and closes immediately. Multiple selection stays in a draft until Apply;
113
+ `onChange(values, options)` returns the complete chosen values **and options**,
114
+ including `([], [])` when cleared. Cancel preserves the applied value.
115
+
116
+ The resource owner supplies authorized `options`, `columns`, optional `getCells`
117
+ (or each option's `cells`), `filters`, `advancedFilters`, `activeFilterCount`, and
118
+ `actions`. Additional buttons belong in `actions`; the shared component retains
119
+ Apply/Cancel. API calls, permissions, filter state, debounce and server sorting
120
+ remain with the owner. `sort`/`onSortChange` expose sortable headers; they do not
121
+ sort a loaded page. `createAction` and `resourceCreateContinuation` keep the
122
+ existing create-and-return contract.
123
+
124
+ Supply `pagination={{ page, pageSize, total, onPageChange }}` for a server page.
125
+ Without pagination, only the supplied collection is searched/paged locally in
126
+ groups of 25; this does not fetch missing records. Controlled search uses
127
+ `searchValue`/`onSearchChange`; the owner resets server pages when scope, filters
128
+ or search change. Controlled search is retained on close, while local search is
129
+ cleared. Optional `open`/`onOpenChange` can enable a query only while open.
130
+ Provide `loading`, `error`, and `onRetry` for changing pages and recovery.
131
+ Provide `selectedOptions` for applied choices absent from the initial page;
132
+ applied labels are retained across subsequent page changes. Values remain the
133
+ source of truth. Scope changes must clear unauthorized selections in the owner.
134
+
135
+ | Earlier draft prop | `NxLookupField` prop |
136
+ |---|---|
137
+ | `presentation="dialog"` | Remove; the component always opens a dialog |
138
+ | `lookupColumns` / `lookupCells` | `columns` / `getCells` |
139
+ | `lookupFilters` / `lookupAdvancedFilters` | `filters` / `advancedFilters` |
140
+ | `lookupActiveFilterCount` / `lookupError` | `activeFilterCount` / `error` |
141
+ | Multi `onChange(values, changedOption)` | `onChange(values, selectedOptions)` |
142
+
143
+ `NxLookupDialog` remains available for composition that already owns its trigger.
144
+ Current-page select-all never means every matching record on the server.
@@ -0,0 +1,11 @@
1
+ ---
2
+ status: published
3
+ version: 0.8.13
4
+ date: 2026-10-24
5
+ title: Shared lookup and document field contracts
6
+ description: Frontend contracts for reusable lookup and document field selection.
7
+ ---
8
+
9
+ - Use `NxLookupField` contracts for single or multiple selection, columns, filters, pagination and authorized creation.
10
+ - Document data and App catalog types preserve source ownership, versions and field identities.
11
+ - Adopt the matching Core 0.8.152 host adapters before using these contracts. Publication does not establish host availability.
@@ -0,0 +1,11 @@
1
+ ---
2
+ status: published
3
+ version: 0.8.13
4
+ date: 2026-10-24
5
+ title: 공통 조회와 문서 필드 계약
6
+ description: 재사용 가능한 조회 및 문서 필드 선택용 프런트엔드 계약을 제공합니다.
7
+ ---
8
+
9
+ - `NxLookupField` 계약으로 단일·다중 선택, 열, 필터, 페이지 이동 및 권한에 따른 생성을 연결합니다.
10
+ - 문서 데이터와 앱 카탈로그 타입이 소스 소유자, 버전 및 필드 식별자를 보존합니다.
11
+ - 사용 전 대응 Core 0.8.152 호스트 어댑터를 채택해야 합니다. 패키지 게시만으로 호스트 사용 가능 상태가 보장되지는 않습니다.
@@ -5,3 +5,35 @@ status: draft
5
5
  The `organization.workforce` v1 slot lets Apps supply workforce views for an authorized Legal Entity. The detailed guide covers props, registration, scoped permissions, and verification.
6
6
 
7
7
  [Implement the workforce slot](https://developers.nexia.to/docs/platform-extensions-add-slot-widget)
8
+
9
+ ### Search and select records in context
10
+
11
+ Apps can use `NxLookupDialog` for paginated record selection with search,
12
+ owner-provided filters, sorting, and single or multiple selection. Draft choices
13
+ survive page and search changes; Apply commits the choices and Cancel preserves
14
+ the caller's previous value. Current-page selection is distinct from selecting
15
+ all records matching a query. Adopt the matching Core host before using this
16
+ new frontend SDK export; queries and access checks remain owner responsibilities.
17
+
18
+ Single-choice callers can set `multiple={false} applyOnSelect` to hide selection controls and apply/close immediately when a row is chosen.
19
+
20
+ ### Dedicated lookup fields
21
+
22
+ Use `NxLookupField` for record lookup fields, with owner-defined columns,
23
+ filters, actions and pagination. It preserves applied choices across pages and
24
+ keeps multiple-selection changes pending until Apply. The earlier draft
25
+ `NxCombobox` dialog API is removed: migrate to `NxLookupField`, rename the
26
+ lookup-prefixed props, and receive all selected options in the multiple
27
+ `onChange` callback. Adopt the matching SDK and Core host together; no released
28
+ minimum version is declared by this draft. See the
29
+ [frontend host guide](https://developers.nexia.to/docs/app-sdk-frontend-host-contracts#dedicated-lookup-fields).
30
+
31
+
32
+ ## Shared document field selection
33
+
34
+ `NxDocumentDataFieldPicker` accepts an App-owned metadata loader and returns a
35
+ stable field binding. It supports App/source/field browsing, server search, paging
36
+ and retry. `buildAppCatalogTree` shares grouping for already-authorized choices.
37
+ Adopt the matching Core host before using these exports; no released minimum
38
+ version is declared by this draft. See the
39
+ [frontend host guide](https://developers.nexia.to/docs/app-sdk-frontend-host-contracts).
@@ -5,3 +5,34 @@ status: draft
5
5
  `organization.workforce` v1 슬롯으로 App이 권한 있는 법인의 직원 배치 보기를 제공할 수 있습니다. 상세 문서에서 props, 등록, 범위별 권한과 확인 방법을 설명합니다.
6
6
 
7
7
  [직원 배치 슬롯 구현하기](https://developers.nexia.to/ko/docs/platform-extensions-add-slot-widget)
8
+
9
+ ### 작업 중 레코드 검색·선택
10
+
11
+ 앱에서 `NxLookupDialog`를 사용해 검색, 앱이 제공하는 필터, 정렬과 페이지
12
+ 이동을 갖춘 단일·복수 선택 화면을 구성할 수 있습니다. 검색어나 페이지를
13
+ 바꿔도 임시 선택이 유지되며, 적용하면 반영하고 취소하면 기존 값을 유지합니다.
14
+ 현재 페이지 선택은 검색 결과 전체 선택과 구분됩니다. 이 프런트엔드 SDK
15
+ 내보내기를 사용하기 전에 대응하는 Core 호스트를 적용해야 하며, 조회와
16
+ 접근 권한 검사는 데이터를 제공하는 쪽이 계속 담당합니다.
17
+
18
+ 단일 선택에서는 `multiple={false} applyOnSelect`로 선택 표시를 숨기고 항목을 고르는 즉시 적용·닫기 동작을 사용할 수 있습니다.
19
+
20
+ ### 독립 조회 필드
21
+
22
+ `NxLookupField`로 리소스별 컬럼·필터·추가 버튼·페이지네이션을 갖춘 조회 필드를
23
+ 구성합니다. 페이지가 바뀌어도 적용된 선택을 보존하고 다중 선택은 적용 전까지
24
+ 임시 상태로 유지합니다. 이전 초안의 `NxCombobox` dialog API를 제거하므로
25
+ `NxLookupField`로 교체하고 조회 전용 속성 이름을 변경하세요. 다중 `onChange`는
26
+ 전체 선택 옵션을 반환합니다. 대응하는 SDK와 Core 호스트를 함께 적용해야 하며,
27
+ 이 초안에서 출시된 최소 버전은 지정하지 않습니다. 자세한 이관 방법은
28
+ [프런트엔드 호스트 가이드](https://developers.nexia.to/ko/docs/app-sdk-frontend-host-contracts#독립-조회-필드)에 있습니다.
29
+
30
+
31
+ ## 공통 문서 필드 선택
32
+
33
+ `NxDocumentDataFieldPicker`는 앱이 제공하는 메타데이터 조회 함수로 앱·소스·필드를
34
+ 탐색하고 고정된 필드 연결을 반환합니다. 서버 검색·페이지·재시도를 지원하며,
35
+ `buildAppCatalogTree`는 이미 인가된 선택지의 그룹 구성을 공유합니다.
36
+ 대응하는 Core 호스트를 먼저 적용해야 합니다. 이 초안에서 출시된 최소 버전은
37
+ 지정하지 않으며 자세한 내용은
38
+ [프런트엔드 호스트 가이드](https://developers.nexia.to/ko/docs/app-sdk-frontend-host-contracts)에 있습니다.
@@ -0,0 +1,13 @@
1
+ import type { NxColumnNode } from './shell';
2
+ export interface AppCatalogGroup {
3
+ key: string;
4
+ label: string;
5
+ order?: number;
6
+ }
7
+ export interface AppCatalogLeaf {
8
+ family: AppCatalogGroup;
9
+ app: AppCatalogGroup;
10
+ node?: NxColumnNode;
11
+ }
12
+ /** Shared presentation only. Consumers supply their already-authorized choices. */
13
+ export declare function buildAppCatalogTree(entries: readonly AppCatalogLeaf[]): NxColumnNode[];
@@ -0,0 +1,18 @@
1
+ /** Shared presentation only. Consumers supply their already-authorized choices. */
2
+ export function buildAppCatalogTree(entries) {
3
+ const families = new Map();
4
+ for (const entry of entries) {
5
+ if (!families.has(entry.family.key))
6
+ families.set(entry.family.key, { group: entry.family, apps: new Map() });
7
+ const apps = families.get(entry.family.key).apps;
8
+ if (!apps.has(entry.app.key))
9
+ apps.set(entry.app.key, { group: entry.app, children: [] });
10
+ if (entry.node)
11
+ apps.get(entry.app.key).children.push(entry.node);
12
+ }
13
+ const order = (a, b) => (a.group.order ?? 999) - (b.group.order ?? 999)
14
+ || a.group.key.localeCompare(b.group.key, undefined, { sensitivity: 'base' });
15
+ return [...families.values()].sort(order).map(({ group, apps }) => ({ value: `family:${group.key}`, label: group.label,
16
+ children: [...apps.values()].sort(order).map(({ group: app, children }) => ({ value: `app:${app.key}`, label: app.label, children })),
17
+ }));
18
+ }
@@ -0,0 +1,57 @@
1
+ export interface DocumentDataFieldBinding {
2
+ app_key: string;
3
+ source_key: string;
4
+ source_version: number;
5
+ field_key: string;
6
+ }
7
+ export interface DocumentDataCatalogItem {
8
+ app_key: string;
9
+ app_name: string;
10
+ app_family?: string;
11
+ app_labels?: Record<string, string>;
12
+ source_key?: string;
13
+ source_version?: number;
14
+ label?: string;
15
+ label_key?: string;
16
+ cardinality?: 'one' | 'many';
17
+ field?: {
18
+ key: string;
19
+ label: string;
20
+ label_key: string;
21
+ type: string;
22
+ formatters: string[];
23
+ };
24
+ binding?: DocumentDataFieldBinding;
25
+ sample?: unknown;
26
+ legacy_source?: string;
27
+ }
28
+ export interface DocumentDataCatalogFilters {
29
+ stage: 'apps' | 'sources' | 'fields';
30
+ app_key?: string;
31
+ source_key?: string;
32
+ source_version?: number;
33
+ q?: string;
34
+ offset?: number;
35
+ limit?: number;
36
+ }
37
+ export interface DocumentDataCatalogPage {
38
+ data: DocumentDataCatalogItem[];
39
+ next_offset: number | null;
40
+ local_fields?: {
41
+ source: string;
42
+ label_key: string;
43
+ }[];
44
+ }
45
+ export interface NxDocumentDataFieldPickerProps {
46
+ open: boolean;
47
+ onClose: () => void;
48
+ title: string;
49
+ loadPage: (filters: DocumentDataCatalogFilters) => Promise<DocumentDataCatalogPage>;
50
+ onSelect: (field: DocumentDataCatalogItem | {
51
+ local_source: string;
52
+ label: string;
53
+ }) => void;
54
+ isDisabled?: (field: DocumentDataCatalogItem) => boolean;
55
+ }
56
+ /** Save this exact tuple, never a list index, label or field-group position. */
57
+ export declare function documentDataFieldIdentity(binding: DocumentDataFieldBinding): string;
@@ -0,0 +1,4 @@
1
+ /** Save this exact tuple, never a list index, label or field-group position. */
2
+ export function documentDataFieldIdentity(binding) {
3
+ return JSON.stringify([binding.app_key, binding.source_key, binding.source_version, binding.field_key]);
4
+ }
package/dist/host.d.ts CHANGED
@@ -1,3 +1,7 @@
1
+ import type { NxDocumentDataFieldPickerProps } from './document-data';
2
+ export type { NxDocumentDataFieldPickerProps } from './document-data';
3
+ import type { NxLookupDialogProps, NxLookupFieldProps } from "./shell";
4
+ export type { NxLookupDialogProps, NxLookupRow, NxLookupFieldProps, NxLookupOption } from "./shell";
1
5
  import type { NxSpreadsheetEditorProps } from "./spreadsheet";
2
6
  import { type ComponentType, type ReactNode } from 'react';
3
7
  import type { AxiosInstance } from 'axios';
@@ -172,6 +176,9 @@ export interface NexiaAppFrontendHostBindings {
172
176
  NxCheckbox: typeof NxCheckbox;
173
177
  NxColumnBrowser: typeof NxColumnBrowser;
174
178
  NxColumnPicker: typeof NxColumnPicker;
179
+ NxDocumentDataFieldPicker: (props: NxDocumentDataFieldPickerProps) => ReactNode;
180
+ NxLookupDialog: (props: NxLookupDialogProps) => ReactNode;
181
+ NxLookupField: <TValue extends string | number>(props: NxLookupFieldProps<TValue>) => ReactNode;
175
182
  NxCombobox: <TValue extends string | number>(props: NxComboboxProps<TValue>) => ReactNode;
176
183
  NxOperatingUnitSelector: ComponentType<NxOperatingUnitSelectorProps>;
177
184
  NxOrganizationTargetSelector: ComponentType<NxOrganizationTargetSelectorProps>;
@@ -401,6 +408,7 @@ export declare function NxRefreshControl(props: NxRefreshControlProps): ReactNod
401
408
  export declare function NxColumnBrowser(props: NxColumnBrowserProps): ReactNode;
402
409
  export declare function NxColumnPicker(props: NxColumnPickerProps): ReactNode;
403
410
  export declare function NxCombobox<TValue extends string | number>(props: NxComboboxProps<TValue>): ReactNode;
411
+ export declare function NxLookupField<TValue extends string | number>(props: NxLookupFieldProps<TValue>): ReactNode;
404
412
  export declare function NxOperatingUnitSelector(props: NxOperatingUnitSelectorProps): ReactNode;
405
413
  export declare function NxOrganizationTargetSelector(props: NxOrganizationTargetSelectorProps): ReactNode;
406
414
  export declare function NxActions(props: NxActionsProps): ReactNode;
@@ -669,3 +677,5 @@ export declare const resourceInspectorAdapterRegistry: ResourceInspectorAdapterR
669
677
  /** Shared spreadsheet editor; the caller owns document persistence. */
670
678
  export declare function NxSpreadsheetEditor(props: NxSpreadsheetEditorProps): ReactNode;
671
679
  import type { NxActionsProps } from './actions';
680
+ export declare function NxLookupDialog(props: NxLookupDialogProps): ReactNode;
681
+ export declare function NxDocumentDataFieldPicker(props: NxDocumentDataFieldPickerProps): ReactNode;
package/dist/host.js CHANGED
@@ -299,6 +299,9 @@ export function NxColumnPicker(props) {
299
299
  export function NxCombobox(props) {
300
300
  return createElement((host().components.NxCombobox), props);
301
301
  }
302
+ export function NxLookupField(props) {
303
+ return createElement((host().components.NxLookupField), props);
304
+ }
302
305
  export function NxOperatingUnitSelector(props) {
303
306
  return render(host().components.NxOperatingUnitSelector, props);
304
307
  }
@@ -947,3 +950,9 @@ export const resourceInspectorAdapterRegistry = {
947
950
  export function NxSpreadsheetEditor(props) {
948
951
  return render(host().components.NxSpreadsheetEditor, props);
949
952
  }
953
+ export function NxLookupDialog(props) {
954
+ return render(host().components.NxLookupDialog, props);
955
+ }
956
+ export function NxDocumentDataFieldPicker(props) {
957
+ return render(host().components.NxDocumentDataFieldPicker, props);
958
+ }
package/dist/index.d.ts CHANGED
@@ -42,3 +42,8 @@ export type { FavoriteButtonProps } from "./host";
42
42
  export { createSpreadsheetWorkbook } from "./spreadsheet";
43
43
  export type { SpreadsheetWorkbook, SpreadsheetWorksheet, SpreadsheetCell, NxSpreadsheetEditorProps } from "./spreadsheet";
44
44
  export type { ActionPlacement, ActionTargets, NxActionsProps } from './actions';
45
+ export type { NxLookupDialogProps, NxLookupRow, NxLookupFieldProps, NxLookupOption } from "./shell";
46
+ export { documentDataFieldIdentity } from './document-data';
47
+ export type { DocumentDataFieldBinding, DocumentDataCatalogItem, DocumentDataCatalogFilters, DocumentDataCatalogPage, NxDocumentDataFieldPickerProps } from './document-data';
48
+ export { buildAppCatalogTree } from './app-catalog';
49
+ export type { AppCatalogGroup, AppCatalogLeaf } from './app-catalog';
package/dist/index.js CHANGED
@@ -20,3 +20,5 @@ export { APPROVAL_STATES, APPROVAL_STEP_KINDS } from "./approval.js";
20
20
  export { DMN_EDITOR_HIT_POLICIES } from "./process.js";
21
21
  export { FavoriteButton } from "./host.js";
22
22
  export { createSpreadsheetWorkbook } from "./spreadsheet.js";
23
+ export { documentDataFieldIdentity } from './document-data.js';
24
+ export { buildAppCatalogTree } from './app-catalog.js';
package/dist/shell.d.ts CHANGED
@@ -108,6 +108,10 @@ export interface NxModalDialogProps {
108
108
  showClose?: boolean;
109
109
  }
110
110
  export interface NxColumnNode {
111
+ section?: {
112
+ key: string;
113
+ label: string;
114
+ };
111
115
  value: string;
112
116
  label: string;
113
117
  children?: NxColumnNode[];
@@ -124,6 +128,10 @@ export interface NxColumnBrowserLabels {
124
128
  breadcrumbSeparator?: string;
125
129
  }
126
130
  export interface NxColumnBrowserProps {
131
+ onBrowse?: (value: string | null) => void;
132
+ onSearchChange?: (query: string) => void;
133
+ remoteSearchResults?: NxColumnNode[];
134
+ notice?: ReactNode;
127
135
  roots: NxColumnNode[];
128
136
  value?: string | null;
129
137
  selectedValues?: readonly string[];
@@ -147,6 +155,10 @@ export interface NxColumnPickerLabels extends NxColumnBrowserLabels {
147
155
  select?: string;
148
156
  }
149
157
  interface NxColumnPickerBaseProps {
158
+ onBrowse?: (value: string | null) => void;
159
+ onSearchChange?: (query: string) => void;
160
+ remoteSearchResults?: NxColumnNode[];
161
+ notice?: ReactNode;
150
162
  open: boolean;
151
163
  onClose: () => void;
152
164
  title: string;
@@ -1410,4 +1422,131 @@ export interface MutationFormError {
1410
1422
  formError: string | null;
1411
1423
  fieldErrors: FormFieldErrors;
1412
1424
  }
1425
+ /** A bounded server page. Selection survives search and page changes until Apply. */
1426
+ export interface NxLookupRow {
1427
+ value: string;
1428
+ label: string;
1429
+ cells: Record<string, ReactNode>;
1430
+ disabled?: boolean;
1431
+ disabledReason?: string;
1432
+ }
1433
+ /** An authorized choice; the owner may attach resource-specific data. */
1434
+ export interface NxLookupOption<TValue extends string | number> {
1435
+ value: TValue;
1436
+ label: ReactNode;
1437
+ meta?: ReactNode;
1438
+ trailing?: ReactNode;
1439
+ searchText?: string;
1440
+ cells?: Record<string, ReactNode>;
1441
+ disabled?: boolean;
1442
+ disabledReason?: string;
1443
+ }
1444
+ interface NxLookupFieldBaseProps<TValue extends string | number> {
1445
+ options: readonly NxLookupOption<TValue>[];
1446
+ /** Supply applied choices that are absent from the current server page. */
1447
+ selectedOptions?: readonly NxLookupOption<TValue>[];
1448
+ placeholder: ReactNode;
1449
+ ariaLabel: string;
1450
+ description?: string;
1451
+ id?: string;
1452
+ describedBy?: string;
1453
+ invalid?: boolean;
1454
+ fullWidth?: boolean;
1455
+ disabled?: boolean;
1456
+ size?: "xs" | "sm" | "md";
1457
+ triggerClassName?: string;
1458
+ testId?: string;
1459
+ /** Optional controlled open state, e.g. to enable an owner query on open. */
1460
+ open?: boolean;
1461
+ onOpenChange?: (open: boolean) => void;
1462
+ searchValue?: string;
1463
+ onSearchChange?: (query: string) => void;
1464
+ searchPlaceholder?: string;
1465
+ emptyLabel?: ReactNode;
1466
+ searchOptions?: {
1467
+ scopeKey: string;
1468
+ search: (query: string, signal?: AbortSignal) => Promise<readonly NxLookupOption<TValue>[]>;
1469
+ };
1470
+ /** Omit only when options is the complete authorized collection. */
1471
+ pagination?: {
1472
+ page: number;
1473
+ pageSize: number;
1474
+ total: number;
1475
+ onPageChange: (page: number) => void;
1476
+ };
1477
+ columns?: readonly {
1478
+ key: string;
1479
+ label: string;
1480
+ sortable?: boolean;
1481
+ }[];
1482
+ getCells?: (option: NxLookupOption<TValue>) => Record<string, ReactNode>;
1483
+ filters?: ReactNode;
1484
+ advancedFilters?: ReactNode;
1485
+ activeFilterCount?: number;
1486
+ /** Additional owner actions beside the search/filter controls. */
1487
+ actions?: ReactNode;
1488
+ sort?: string;
1489
+ onSortChange?: (sort: string) => void;
1490
+ loading?: boolean;
1491
+ error?: string | null;
1492
+ onRetry?: () => void;
1493
+ maxSelection?: number;
1494
+ renderSummary?: (selected: NxLookupOption<TValue>[]) => ReactNode;
1495
+ showSelectedItems?: boolean;
1496
+ selectedItemsAriaLabel?: string;
1497
+ removeSelectedItemLabel?: (option: NxLookupOption<TValue>) => string;
1498
+ createAction?: {
1499
+ label: string;
1500
+ onCreate: (query: string) => void;
1501
+ disabled?: boolean;
1502
+ };
1503
+ revalidateOnOpen?: ResourcePickerRevalidation;
1504
+ resourceCreateContinuation?: TValue extends string ? ResourceCreateContinuationTarget : never;
1505
+ }
1506
+ /** A field that opens a lookup dialog; it has no popover presentation. */
1507
+ export type NxLookupFieldProps<TValue extends string | number> = (NxLookupFieldBaseProps<TValue> & {
1508
+ multiple?: false;
1509
+ value: TValue | null;
1510
+ onChange: (value: TValue, option: NxLookupOption<TValue>) => void;
1511
+ }) | (NxLookupFieldBaseProps<TValue> & {
1512
+ multiple: true;
1513
+ value: readonly TValue[];
1514
+ /** Complete applied selection, including [] when cleared. */
1515
+ onChange: (values: TValue[], options: NxLookupOption<TValue>[]) => void;
1516
+ });
1517
+ export interface NxLookupDialogProps {
1518
+ open: boolean;
1519
+ onClose: () => void;
1520
+ title: string;
1521
+ description?: string;
1522
+ multiple?: boolean;
1523
+ /** Single selection only: hide selection controls, apply a row immediately, then call onClose. */
1524
+ applyOnSelect?: boolean;
1525
+ value: readonly NxLookupRow[];
1526
+ onApply: (rows: NxLookupRow[]) => void;
1527
+ rows: readonly NxLookupRow[];
1528
+ columns: readonly {
1529
+ key: string;
1530
+ label: string;
1531
+ sortable?: boolean;
1532
+ }[];
1533
+ search: string;
1534
+ onSearchChange: (value: string) => void;
1535
+ searchPlaceholder?: string;
1536
+ emptyLabel?: ReactNode;
1537
+ filters?: ReactNode;
1538
+ actions?: ReactNode;
1539
+ advancedFilters?: ReactNode;
1540
+ activeFilterCount?: number;
1541
+ page: number;
1542
+ pageSize: number;
1543
+ total: number;
1544
+ onPageChange: (page: number) => void;
1545
+ sort?: string;
1546
+ onSortChange?: (sort: string) => void;
1547
+ loading?: boolean;
1548
+ error?: string | null;
1549
+ onRetry?: () => void;
1550
+ maxSelection?: number;
1551
+ }
1413
1552
  export {};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nexia/sdk",
3
- "version": "0.8.12",
3
+ "version": "0.8.13",
4
4
  "description": "Frontend contracts for Nexia App Packages",
5
5
  "license": "UNLICENSED",
6
6
  "type": "module",