@orangelogic/orange-dam-content-browser-sdk 2.4.8 → 2.4.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (26) hide show
  1. package/build/GlobalConfigContext.d.ts +4 -0
  2. package/build/OrangeDAMContentBrowserSDK.min.js +738 -337
  3. package/build/api/asset/asset.d.ts +2 -1
  4. package/build/api/asset/asset.types.d.ts +9 -0
  5. package/build/components/content-browser/content-browser.d.ts +73 -2
  6. package/build/components/content-browser-asset-card/content-browser-asset-card.d.ts +25 -1
  7. package/build/components/content-browser-control-bar/content-browser-control-bar.d.ts +1 -0
  8. package/build/components/content-browser-control-view/content-browser-control-view.d.ts +5 -2
  9. package/build/components/content-browser-format-dialog/content-browser-format-dialog.d.ts +27 -1
  10. package/build/components/content-browser-grid/content-browser-grid.d.ts +5 -1
  11. package/build/components/content-browser-table/column-layout.d.ts +29 -0
  12. package/build/components/content-browser-table/content-browser-table.d.ts +302 -0
  13. package/build/components/content-browser-table/content-browser-table.styles.d.ts +2 -0
  14. package/build/content-browser.mjs +2506 -450
  15. package/build/events/cx-content-browser-control-view-change.d.ts +2 -2
  16. package/build/events/cx-content-browser-request-change.d.ts +2 -2
  17. package/build/events/cx-content-browser-table-column-resize.d.ts +26 -0
  18. package/build/events/index.d.ts +1 -0
  19. package/build/index.d.ts +40 -2
  20. package/build/index.html +4 -0
  21. package/build/index.mjs +2531 -635
  22. package/build/tools/fetch-and-merge-assets.d.ts +15 -3
  23. package/build/types/asset.d.ts +5 -0
  24. package/build/types/content-browser.d.ts +69 -0
  25. package/build/utils/table-column-widths.d.ts +5 -0
  26. package/package.json +2 -2
@@ -36,7 +36,8 @@ export declare function resolveAssetExtraFilters(selectedFacets?: Record<string,
36
36
  };
37
37
  export declare function apiGetAssetLinks({ assets, extension, extraFields, parameters, permanentLink, proxyPreference, transformations, useSession, }: GetAssetLinksRequest): Promise<GetAssetLinksResponse>;
38
38
  export declare function apiGetAssetsByIDs({ extraFields, recordIds, }: GetAssetsByIDsRequest): Promise<GetAssetsByIDsResponse>;
39
- export declare function apiGetAssets({ folderId, isSeeThrough, limitedToDocTypes, pageSize, searchText, selectedFacets, sortOrder, start, useSession, }: GetAssetsRequest): Promise<GetAssetsResponse>;
39
+ export declare const ASSET_LIST_FIELDS: string[];
40
+ export declare function apiGetAssets({ fields, folderId, isSeeThrough, limitedToDocTypes, pageSize, searchText, selectedFacets, sortOrder, start, useSession, }: GetAssetsRequest): Promise<GetAssetsResponse>;
40
41
  export declare function apiGetAvailableProxies({ assetRecordId, siteUrl, }: {
41
42
  assetRecordId: string;
42
43
  siteUrl?: string;
@@ -57,12 +57,21 @@ export type GetAssetsRawResponse = {
57
57
  contentItems?: ContentItem[];
58
58
  facets: Facet[];
59
59
  totalCount: number;
60
+ /** Absent on a Cortex build older than L-42BJ3T. */
61
+ unreadableFields?: string[];
60
62
  };
61
63
  export type GetAssetsResponse = {
62
64
  facets: Facet[];
63
65
  isError: boolean;
64
66
  items: Array<Asset & Record<string, string | boolean>>;
65
67
  totalCount: number;
68
+ /**
69
+ * The requested fields, spelled as sent, that the user cannot read on this page of records. Cortex
70
+ * still sends each one on every item, with an empty value, except a field that the
71
+ * `DbBOFieldSecurity_BO.Data.ObjectsInfoRetriever_IgnoredFields` parameter lists, which keeps its
72
+ * value. Empty when Cortex flags none, or when Cortex is too old to flag any.
73
+ */
74
+ unreadableFields: string[];
66
75
  };
67
76
  export type GetAvailableProxiesRequest = {
68
77
  assetRecordId: string;
@@ -6,7 +6,8 @@ import CxContentBrowserFormatDialog from '../../components/content-browser-forma
6
6
  import CxContentBrowserGrid from '../../components/content-browser-grid/content-browser-grid';
7
7
  import CxContentBrowserHeader from '../../components/content-browser-header/content-browser-header';
8
8
  import CxContentBrowserNoResult from '../../components/content-browser-no-result/content-browser-no-result';
9
- import { type CtaTextTransform, GridView } from '../../types/content-browser';
9
+ import CxContentBrowserTable from '../../components/content-browser-table/content-browser-table';
10
+ import { type AutoSelectFormat, type ContentBrowserView, type CtaTextTransform, type TableColumn, type TableRowActionPosition } from '../../types/content-browser';
10
11
  import { GetFolderRequest } from '../../types/folder';
11
12
  import CxIcon from '@orangelogic/design-system/components/icon';
12
13
  import CxIconButton from '@orangelogic/design-system/components/icon-button';
@@ -18,6 +19,7 @@ export declare const COMPUTED_FIELDS: string[];
18
19
  * @summary CxContentBrowser
19
20
  */
20
21
  export default class CxContentBrowser extends CortexElement {
22
+ #private;
21
23
  static readonly styles: CSSResultGroup;
22
24
  static readonly dependencies: {
23
25
  'cx-content-browser-browser': typeof CxContentBrowserBrowser;
@@ -26,6 +28,7 @@ export default class CxContentBrowser extends CortexElement {
26
28
  'cx-content-browser-grid': typeof CxContentBrowserGrid;
27
29
  'cx-content-browser-header': typeof CxContentBrowserHeader;
28
30
  'cx-content-browser-no-result': typeof CxContentBrowserNoResult;
31
+ 'cx-content-browser-table': typeof CxContentBrowserTable;
29
32
  'cx-icon': typeof CxIcon;
30
33
  'cx-icon-button': typeof CxIconButton;
31
34
  'cx-resize-observer': typeof CxResizeObserver;
@@ -61,6 +64,10 @@ export default class CxContentBrowser extends CortexElement {
61
64
  */
62
65
  canPinAsset: boolean;
63
66
  canUseProxies: boolean;
67
+ /**
68
+ * Host-level import behaviour; forwarded to the format dialog. See `AutoSelectFormat`.
69
+ */
70
+ autoSelectFormat: AutoSelectFormat;
64
71
  /**
65
72
  * Pick-only mode: no available-proxies lookup, no transformation on confirm. The preview popup
66
73
  * shows the asset's LargeSizePreview and confirming emits the asset straight to the host.
@@ -73,7 +80,29 @@ export default class CxContentBrowser extends CortexElement {
73
80
  ctaText: string;
74
81
  ctaTextTransform: CtaTextTransform;
75
82
  extraFields: string[];
76
- defaultGridView: GridView;
83
+ defaultGridView: ContentBrowserView;
84
+ /**
85
+ * Columns of the table view, defined by the host: a title and the Cortex field the column reads.
86
+ * The table fits each column to its content, and the user resizes it. The table view is offered only while this is non-empty — an empty table is not a
87
+ * view mode — and the fields are read once, when the fetch controller is created.
88
+ */
89
+ tableColumns: TableColumn[];
90
+ /**
91
+ * Where the row action of the table view shows: at the right edge of the host (`host-edge`), or at
92
+ * the end of the last data column (`row-end`). Any other value gives `host-edge`.
93
+ */
94
+ tableRowActionPosition: TableRowActionPosition;
95
+ /** The widths the user saved for the table columns of this site, in pixels, keyed by field. */
96
+ private tableColumnWidths;
97
+ /**
98
+ * The reads and writes of the saved widths, one after the other: each write reads the stored map
99
+ * and writes it back, and a read that runs before a write would give the table a stale map.
100
+ */
101
+ private tableWidthQueue;
102
+ /** The number of reads and writes queued on `tableWidthQueue`. Only the last one gives its map to the table. */
103
+ private tableWidthTasks;
104
+ /** Set by a drag or a reset that the table shows, until a map from the storage replaces it. */
105
+ private tableWidthsChangedInTable;
77
106
  defaultSortOrderName: string;
78
107
  defaultSortDirection: 'ascending' | 'descending';
79
108
  defaultSelectedFacets: Record<string, string[]>;
@@ -109,6 +138,35 @@ export default class CxContentBrowser extends CortexElement {
109
138
  private initialFolderPending;
110
139
  private initialFolderTimeout;
111
140
  willUpdate(changedProperties: PropertyValues): void;
141
+ /**
142
+ * Never trust the host's value: it also arrives by direct property assignment, past the converter.
143
+ * Entries are checked one by one, not just the outer array — `field` is dereferenced while the
144
+ * fetch controller is being built, where a throw leaves the controller unassigned and the picker
145
+ * blank. `title` is only rendered, and Lit renders a nullish one as nothing, so a column is not
146
+ * worth dropping over it.
147
+ */
148
+ private get tableColumnList();
149
+ /**
150
+ * This reads the configured columns, not the shown ones. The shown columns can change with each
151
+ * response, and a table view that goes away with them flips the view and its page size. When
152
+ * Cortex flags each column, the rows stay with only the filler and the CTA column.
153
+ */
154
+ private get canUseTable();
155
+ /**
156
+ * Runs a read or a write of the saved widths after the ones queued before it. The table gets the
157
+ * map of the last task only: an earlier map does not hold the drags and resets that came after it,
158
+ * and the table already shows them. A map for a site that is no longer the current one is dropped.
159
+ */
160
+ private queueTableWidthTask;
161
+ /**
162
+ * A map with the same entries keeps the old one, so that the table does not lay out its columns
163
+ * again. After a drag or a reset the table can show widths that the old map does not hold, so the
164
+ * new map always replaces them.
165
+ */
166
+ private setTableColumnWidths;
167
+ private loadTableColumnWidths;
168
+ handleBaseUrlChangeForTableWidths(): void;
169
+ private handleTableColumnResize;
112
170
  runFirstUpdated(): void;
113
171
  connectedCallback(): void;
114
172
  disconnectedCallback(): void;
@@ -120,8 +178,20 @@ export default class CxContentBrowser extends CortexElement {
120
178
  * pin/unpin request (see `cx-content-browser-pin-asset-change`) to reflect the result.
121
179
  */
122
180
  setIsAssetPinned(isAssetPinned: boolean): void;
181
+ /**
182
+ * The asset a click is still working on, or undefined. The two private flags below drive the
183
+ * guards; this drives the UI, and is a separate field because they are plain fields rather than
184
+ * reactive state.
185
+ *
186
+ * Cleared the moment the format dialog actually opens: from there the dialog's own confirm button
187
+ * carries the pending state, and two spinners for one operation reads as two operations. It
188
+ * survives when no dialog opens, which is the auto-confirm path, where the CTA is the only thing
189
+ * the user can be told anything by.
190
+ */
191
+ private busyAssetId;
123
192
  private openFormatDialog;
124
193
  handleLastRequestChange(): Promise<void>;
194
+ handleTableColumnsChange(): void;
125
195
  handleAuthChange(): void;
126
196
  handleSiteSessionChange(): void;
127
197
  private handleSortOrderChange;
@@ -144,6 +214,7 @@ export default class CxContentBrowser extends CortexElement {
144
214
  */
145
215
  private handlePinAssetChange;
146
216
  private handleProxyConfirm;
217
+ private reportProxyConfirmFailure;
147
218
  private handleFormatConfirm;
148
219
  private handleFormatDialogClose;
149
220
  private handleSelectedAsset;
@@ -1,8 +1,9 @@
1
1
  import { CSSResultGroup } from 'lit';
2
2
  import CortexElement from '../../base/element';
3
3
  import { MediaType } from '../../types/asset';
4
- import { GridView } from '../../types/content-browser';
4
+ import { type CtaTextTransform, GridView } from '../../types/content-browser';
5
5
  import CxArrayLineClamp from '@orangelogic/design-system/components/array-line-clamp';
6
+ import CxButton from '@orangelogic/design-system/components/button';
6
7
  import CxCard from '@orangelogic/design-system/components/card';
7
8
  import CxCheckbox from '@orangelogic/design-system/components/checkbox';
8
9
  import CxLineClamp from '@orangelogic/design-system/components/line-clamp';
@@ -10,10 +11,19 @@ import CxSpace from '@orangelogic/design-system/components/space';
10
11
  import CxTag from '@orangelogic/design-system/components/tag';
11
12
  import CxTypography from '@orangelogic/design-system/components/typography';
12
13
  import CxContentBrowserAssetPreview from '../content-browser-asset-preview/content-browser-asset-preview';
14
+ /**
15
+ * Grid view is pointer-only by design: the card is not focusable, and its CTA overlay is
16
+ * `aria-hidden` with a `tabindex="-1"` button because the overlay only restates what clicking the
17
+ * card already does. This diverges deliberately from `cx-content-browser-table`, whose rows are
18
+ * focusable and announce their CTA — the grid's keyboard gap predates the table view and closing it
19
+ * would change focus and screen-reader behaviour for every existing host. Revisit together with the
20
+ * grid's own keyboard support rather than per-feature.
21
+ */
13
22
  export default class CxContentBrowserAssetCard extends CortexElement {
14
23
  static readonly styles: CSSResultGroup;
15
24
  static readonly dependencies: {
16
25
  'cx-array-line-clamp': typeof CxArrayLineClamp;
26
+ 'cx-button': typeof CxButton;
17
27
  'cx-card': typeof CxCard;
18
28
  'cx-checkbox': typeof CxCheckbox;
19
29
  'cx-content-browser-asset-preview': typeof CxContentBrowserAssetPreview;
@@ -22,6 +32,20 @@ export default class CxContentBrowserAssetCard extends CortexElement {
22
32
  'cx-tag': typeof CxTag;
23
33
  'cx-typography': typeof CxTypography;
24
34
  };
35
+ private readonly localize;
36
+ /**
37
+ * Show the hover overlay that says clicking this card inserts. Set when the host has asked to
38
+ * skip the format picker: without the dialog a click hands the asset over immediately, and the
39
+ * card would otherwise carry no sign of that.
40
+ */
41
+ showCta: boolean;
42
+ ctaText: string;
43
+ ctaTextTransform: CtaTextTransform;
44
+ /**
45
+ * This card's insert is still running: hold the overlay open and spin its CTA, so the feedback
46
+ * does not vanish the moment the pointer leaves.
47
+ */
48
+ busy: boolean;
25
49
  imageUrl: string;
26
50
  originalUrl: string;
27
51
  scrubUrl: string;
@@ -61,6 +61,7 @@ export default class CxContentBrowserControlBar extends CortexElement {
61
61
  newlyChangedOption: ChangeOption | undefined;
62
62
  searchText: string;
63
63
  isMobile: boolean;
64
+ canUseTable: boolean;
64
65
  private handleSearchChange;
65
66
  render(): TemplateResult;
66
67
  }
@@ -10,7 +10,7 @@ import CxSpace from '@orangelogic/design-system/components/space';
10
10
  import CxSwitch from '@orangelogic/design-system/components/switch';
11
11
  import CxTooltip from '@orangelogic/design-system/components/tooltip';
12
12
  import CortexElement from '../../base/element';
13
- import { ControlOption, GridView } from '../../types/content-browser';
13
+ import { type ContentBrowserView, ControlOption } from '../../types/content-browser';
14
14
  import type { CSSResultGroup, TemplateResult } from 'lit';
15
15
  /**
16
16
  * @summary DAM view control toolbar for selecting asset view modes and toggling options.
@@ -41,14 +41,17 @@ export default class CxContentBrowserControlView extends CortexElement {
41
41
  'cx-tooltip': typeof CxTooltip;
42
42
  };
43
43
  private readonly localize;
44
- view: GridView;
44
+ view: ContentBrowserView;
45
45
  views: ControlOption[];
46
46
  isSeeThrough: boolean;
47
47
  isMobile: boolean;
48
+ canUseTable: boolean;
48
49
  private selectedView;
50
+ private get isTable();
49
51
  runConnectedCallback(): void;
50
52
  private handleSeeThroughClick;
51
53
  private handleViewSelect;
54
+ private renderTableOption;
52
55
  handleViewChange(): void;
53
56
  render(): TemplateResult;
54
57
  }
@@ -15,7 +15,7 @@ import CxTypography from '@orangelogic/design-system/components/typography';
15
15
  import CxContentBrowserAssetPreview from '../content-browser-asset-preview/content-browser-asset-preview';
16
16
  import CxContentBrowserAssetProxySelector from '../content-browser-asset-proxy-selector/content-browser-asset-proxy-selector';
17
17
  import CxContentBrowserAssetVersionHistory from '../content-browser-asset-version-history/content-browser-asset-version-history';
18
- import { type Parameter, type Transformation, type CtaTextTransform, ContentBrowserFormatDialogVariant } from '../../types/content-browser';
18
+ import { type Parameter, type Transformation, type CtaTextTransform, type AutoSelectFormat, ContentBrowserFormatDialogVariant } from '../../types/content-browser';
19
19
  export default class CxContentBrowserFormatDialog extends CortexElement {
20
20
  static readonly styles: CSSResultGroup;
21
21
  static readonly dependencies: {
@@ -47,6 +47,12 @@ export default class CxContentBrowserFormatDialog extends CortexElement {
47
47
  canPinAsset: boolean;
48
48
  canTrack: boolean;
49
49
  canUseProxies: boolean;
50
+ /**
51
+ * Skip the format picker and insert directly — see `resolveAutoSelection` for what each value
52
+ * does. Off by default: this changes what a click does, so a host opts in rather than
53
+ * inheriting it.
54
+ */
55
+ autoSelectFormat: AutoSelectFormat;
50
56
  /**
51
57
  * Pick-only mode. Suppresses the custom-format editor entirely: cx-asset-link-format issues its
52
58
  * own transformasset request as soon as it is in the DOM, so hiding it with CSS is not enough.
@@ -97,7 +103,19 @@ export default class CxContentBrowserFormatDialog extends CortexElement {
97
103
  * One rule for the Insert button and handleProxyConfirm, so an enabled Insert always confirms (L-42BIA4).
98
104
  */
99
105
  private get canConfirm();
106
+ private filterProxies;
100
107
  handleSupportedExtensionsChange(): void;
108
+ /**
109
+ * What `autoSelectFormat` resolves to for this asset: the proxy to insert with, or `undefined`
110
+ * when the dialog should open as usual.
111
+ *
112
+ * `{ proxy: undefined }` is deliberate rather than a miss — with the picker switched off there is
113
+ * no format to name and the original file is the only outcome, which is `handleProxyConfirm`'s
114
+ * no-proxy branch. With the picker on a proxy must actually resolve: confirming none emits
115
+ * nothing and would turn the click into a silent no-op, so both an empty proxy list and a format
116
+ * name that matches nothing fall back to the dialog.
117
+ */
118
+ private resolveAutoSelection;
101
119
  open({ asset, isFavorite, isAssetPinned, proxies, proxiesFailed, }: {
102
120
  asset: Asset & {
103
121
  previewUrl: string;
@@ -108,6 +126,14 @@ export default class CxContentBrowserFormatDialog extends CortexElement {
108
126
  proxiesFailed?: boolean;
109
127
  }): void;
110
128
  hide(): void;
129
+ /**
130
+ * Show a dialog that `open()` skipped through the auto-confirm shortcut. The asset, proxies and
131
+ * resolved selection are still in place, so this lands the user on exactly the dialog the
132
+ * shortcut spared them, with its confirm button live again to retry.
133
+ */
134
+ revealAfterAutoConfirm(): void;
135
+ /** Whether the dialog is actually on screen — false when `open()` took the auto-confirm path. */
136
+ get isDialogOpen(): boolean;
111
137
  setVersionHistory(versions: AssetVersion[]): void;
112
138
  setIsFavorite(isFavorite: boolean): void;
113
139
  setIsAssetPinned(isAssetPinned: boolean): void;
@@ -1,7 +1,7 @@
1
1
  import '@lit-labs/virtualizer';
2
2
  import CortexElement from '../../base/element';
3
3
  import { Asset } from '../../types/asset';
4
- import { GridView } from '../../types/content-browser';
4
+ import { GridView, type CtaTextTransform } from '../../types/content-browser';
5
5
  import CxButton from '@orangelogic/design-system/components/button';
6
6
  import CxIcon from '@orangelogic/design-system/components/icon';
7
7
  import CxProgressBar from '@orangelogic/design-system/components/progress-bar';
@@ -34,6 +34,10 @@ export default class CxContentBrowserGrid extends CortexElement {
34
34
  showSize: boolean;
35
35
  showDimensions: boolean;
36
36
  showTags: boolean;
37
+ showCta: boolean;
38
+ ctaText: string;
39
+ ctaTextTransform: CtaTextTransform;
40
+ busyAssetId: string | undefined;
37
41
  selectedAssetId: string | undefined;
38
42
  assetMap: Map<string, Asset>;
39
43
  columnWidth: number;
@@ -0,0 +1,29 @@
1
+ /** The narrowest width a table column can have, in pixels. */
2
+ export declare const MIN_COLUMN_WIDTH = 92;
3
+ /**
4
+ * One column for the layout rules.
5
+ * `natural` is the width the column wants, in pixels.
6
+ * `saved` is the width the user set, in pixels. Leave it out for an auto-fit column.
7
+ */
8
+ export type ColumnLayoutInput = {
9
+ natural: number;
10
+ saved?: number;
11
+ };
12
+ /**
13
+ * Measure the width of a text with a font, in whole pixels.
14
+ * @param text The text to measure.
15
+ * @param font A CSS font value, such as `'14px sans-serif'`.
16
+ * @returns The width of the text, rounded up. Returns 0 when no canvas context is available.
17
+ */
18
+ export declare function measureTextWidth(text: string, font: string): number;
19
+ /**
20
+ * Lay out the column widths inside the available width.
21
+ * Saved widths keep their size. Auto-fit columns that fit in a fair share keep their natural
22
+ * width. The other auto-fit columns share the space that is left. Spare space goes to the
23
+ * auto-fit columns in equal parts. No column is narrower than MIN_COLUMN_WIDTH, so the result can
24
+ * be wider than `available`.
25
+ * @param columns The columns, in display order.
26
+ * @param available The width of the host, in pixels.
27
+ * @returns One whole-pixel width for each column, in the same order.
28
+ */
29
+ export declare function layoutColumnWidths(columns: ColumnLayoutInput[], available: number): number[];
@@ -0,0 +1,302 @@
1
+ import { type PropertyValues } from 'lit';
2
+ import CortexElement from '../../base/element';
3
+ import { Asset } from '../../types/asset';
4
+ import { type CtaTextTransform, TableColumn, type TableRowActionPosition } from '../../types/content-browser';
5
+ import CxButton from '@orangelogic/design-system/components/button';
6
+ import CxIcon from '@orangelogic/design-system/components/icon';
7
+ import CxLineClamp from '@orangelogic/design-system/components/line-clamp';
8
+ import CxProgressBar from '@orangelogic/design-system/components/progress-bar';
9
+ import CxResizeObserver from '@orangelogic/design-system/components/resize-observer';
10
+ import CxContentBrowserNoResult from '../content-browser-no-result/content-browser-no-result';
11
+ import { MIN_COLUMN_WIDTH } from './column-layout';
12
+ import type { CSSResultGroup } from 'lit';
13
+ /** `cx-table`'s own row height, the one every other Cortex table renders at. */
14
+ export declare const ROW_HEIGHT = 48;
15
+ /** Kept here too, so the old import path of the column floor stays valid. */
16
+ export { MIN_COLUMN_WIDTH };
17
+ /** An invisible column keeps Tabulator rows present when every data column is hidden. */
18
+ export declare const FILLER_FIELD = "filler";
19
+ /**
20
+ * Column values ride on the asset under the Cortex field name as requested (see `apiGetAssets`),
21
+ * which `Asset` cannot declare because the field set is the host's, not the SDK's. Read as an own
22
+ * property: a field named after an `Object.prototype` member (`toString`, `constructor`) would
23
+ * otherwise read back the inherited function.
24
+ */
25
+ export declare function readCellValue(asset: Asset, field: string): string;
26
+ /**
27
+ * @summary Table layout for the Content Browser: one row per asset, host-configured metadata columns
28
+ * instead of a thumbnail, rendered by the design system's `cx-table`.
29
+ *
30
+ * @description Renders the same asset list the grid does and emits the same item events, so an asset
31
+ * with no rendition — a text fragment, `digitized = 0` — is browsable and selectable by its
32
+ * identifying fields. It fetches nothing of its own: a row exists, and a cell has a value, only
33
+ * because the search response the grid also consumes carried it.
34
+ *
35
+ * @event cx-content-browser-grid-click - Emitted when a row's CTA button is activated, by a click or
36
+ * from the keyboard: once for a double click on it, and never for a click or a double click on the
37
+ * row itself.
38
+ * @event cx-content-browser-grid-resize - Emitted when the number of rows the visible scrollport can
39
+ * show changes, and again once a restarted list's rows are in, so the host can grow the page size.
40
+ * A count measured while a page of the shown list loads is emitted once the load ends and any
41
+ * rows it brings are in. A count measured after the load ends is emitted at once, and it can come
42
+ * before the rows of a new list are in.
43
+ * @event cx-content-browser-grid-retry - Emitted when the user clicks Retry after a search error.
44
+ * @event cx-content-browser-grid-scroll-end - Emitted while `has-more` is set, no page is loading, and
45
+ * the last row comes into view: by scrolling the table's own scrollport, or by scrolling the page when
46
+ * a table taller than the viewport holds its rows without overflowing and so never scrolls itself.
47
+ * @event cx-content-browser-table-column-resize - Emitted when a host-configured column settles on a
48
+ * new width: a drag of its divider released (`detail.reset` is `false`), or a double click on the
49
+ * divider that removes the saved width and auto-fits the column (`detail.reset` is `true`). The
50
+ * filler and the row action have no divider. `detail.width` is the column's width in whole pixels,
51
+ * and is never `undefined`. The SDK saves the width itself.
52
+ */
53
+ export default class CxContentBrowserTable extends CortexElement {
54
+ #private;
55
+ static readonly styles: CSSResultGroup;
56
+ static readonly dependencies: {
57
+ 'cx-button': typeof CxButton;
58
+ 'cx-content-browser-no-result': typeof CxContentBrowserNoResult;
59
+ 'cx-icon': typeof CxIcon;
60
+ 'cx-line-clamp': typeof CxLineClamp;
61
+ 'cx-progress-bar': typeof CxProgressBar;
62
+ 'cx-resize-observer': typeof CxResizeObserver;
63
+ 'cx-table': typeof import("node_modules/@orangelogic/design-system/library/packages/hybrid/table-core/src").default;
64
+ };
65
+ private readonly localize;
66
+ private readonly containerEl;
67
+ private readonly tableEl;
68
+ assets: Asset[];
69
+ columns: TableColumn[];
70
+ ctaText: string;
71
+ ctaTextTransform: CtaTextTransform;
72
+ empty: boolean;
73
+ /** The last search request got an error. With no rows, the error replaces the table. With rows, it shows at the bottom. */
74
+ error: boolean;
75
+ hasMore: boolean;
76
+ loading: boolean;
77
+ selectedAssetId: string | undefined;
78
+ /**
79
+ * The asset whose insert is still running, so its row keeps the CTA on screen and spinning.
80
+ */
81
+ busyAssetId: string | undefined;
82
+ /**
83
+ * Fields of `columns`, compared exactly, whose columns the table does not show. A hidden column
84
+ * keeps its place, its cell values and a dragged width, so it comes back with the rows and the
85
+ * scroll position unchanged. The filler and the row action remain when every host column is hidden.
86
+ */
87
+ hiddenFields: string[];
88
+ /**
89
+ * The widths that the user saved, in pixels, keyed by the trimmed `field`. A column with a saved
90
+ * width shows at that width. The other columns auto-fit to their content. A new map replaces the
91
+ * old one, the drags and resets in memory included.
92
+ */
93
+ savedWidths: Record<string, number>;
94
+ /**
95
+ * The owner of `savedWidths`, such as the Cortex site. A new value drops the widths that a drag
96
+ * held for the session. A new `savedWidths` for the same owner keeps them.
97
+ */
98
+ widthScope: string | undefined;
99
+ /**
100
+ * Where the row action shows: at the right edge of the host (`host-edge`), or at the end of the
101
+ * last data column (`row-end`).
102
+ */
103
+ rowActionPosition: TableRowActionPosition;
104
+ assetMap: Map<string, Asset>;
105
+ private get tabulator();
106
+ /**
107
+ * The current Tabulator instance, built or not. Tabulator shows its header and frame as it builds,
108
+ * but fires `tableBuilt` only after its data-load debounce.
109
+ */
110
+ private get buildingTabulator();
111
+ /** Tabulator's row holder: the one element that scrolls the rows. */
112
+ private get scrollport();
113
+ /** Each host column's row key, in order: a field the host repeats takes a key per occurrence. */
114
+ private resolveColumnKeys;
115
+ private buildColumnDefinitions;
116
+ /**
117
+ * A pixel width for each column, so the `fitData` layout never sizes it from its content. The
118
+ * auto-fit sets the real width once the columns are built (see `applyColumnLayout`). Until then a
119
+ * column keeps the width it had in the previous definitions.
120
+ */
121
+ private buildDataColumnDefinitions;
122
+ /**
123
+ * Tabulator replaces its rows with a placeholder when no columns remain visible. This invisible
124
+ * column keeps the rows and their actions available when the host hides every data column.
125
+ * Its small, fixed width gives the final resize handle a buffer without a visible empty column.
126
+ */
127
+ private buildFillerColumnDefinition;
128
+ private get ctaLabel();
129
+ /** The action overlays its row and takes no column width. */
130
+ private renderRowAction;
131
+ private isCtaShown;
132
+ /** In place, never rebuilt: a new button would drop the keyboard focus the old one held. */
133
+ private paintCta;
134
+ private paintRowCta;
135
+ private paintAssetCta;
136
+ private trackPointer;
137
+ private setHoveredRow;
138
+ /**
139
+ * Tabulator takes a row that scrolls out of its render window off the page, and a row taken off
140
+ * the page gets no `mouseleave` to hide its CTA, nor need its button get a `focusout` for the
141
+ * focus it drops.
142
+ */
143
+ private releaseDetachedCta;
144
+ /** Lays the columns and the rendered rows out again. */
145
+ private redrawTable;
146
+ /** The frame ends at the data columns. The scrollport remains available to the row actions. */
147
+ private syncTableFrame;
148
+ /**
149
+ * Tabulator renders the rows again -- for an appended page, a redraw of its own or one of ours --
150
+ * by taking every rendered row off the page and back, which drops the keyboard focus, so the CTA
151
+ * that held it gets it back.
152
+ */
153
+ private handleRenderStarted;
154
+ private handleRenderComplete;
155
+ private toRow;
156
+ private findRow;
157
+ /**
158
+ * `aria-current`, not `aria-selected`: this is a `grid` with no selection model of its own. The
159
+ * row is never selected in Tabulator, so an import does not paint `cx-table`'s selected-row highlight.
160
+ */
161
+ private markCurrentRow;
162
+ /**
163
+ * The fonts and the padding of a rendered header title and data cell. A table with no rendered
164
+ * cell measures the values in the header font, with the header padding.
165
+ */
166
+ private readColumnMetrics;
167
+ private getScrollbarWidth;
168
+ /** The widest of the title and the values of the loaded rows, plus the padding. */
169
+ private measureNaturalWidth;
170
+ /**
171
+ * Sets the width of each visible host column: a saved or session width as is, and an auto-fit
172
+ * width for the other columns, inside the width of the table (see `layoutColumnWidths`). A hidden
173
+ * column keeps its width. A table with no width, as one in a hidden panel, keeps its widths until
174
+ * it is shown.
175
+ * @param measure Measure the natural widths again. Leave it false to reuse the natural widths of
176
+ * the last full layout, for a change of the available width only.
177
+ */
178
+ private applyColumnLayout;
179
+ /**
180
+ * The canvas measures with a fallback font while a web font loads, so measure again once the fonts
181
+ * are ready. Guarded by one pending wait, and by the connection of the element.
182
+ */
183
+ private layoutAgainWhenFontsLoad;
184
+ private readonly debouncedApplyColumnLayout;
185
+ /**
186
+ * `content-browser` hands over the whole list on every page, so a list that only grows by a page
187
+ * is appended: reassigning it would call `setData`, which scrolls the table back to the top. Any
188
+ * other list -- a new search, sort, filter or folder, or a refetch that brings the assets the rows
189
+ * show as new objects -- replaces the rows.
190
+ */
191
+ private syncRows;
192
+ private handleTableBuilt;
193
+ /**
194
+ * Gives the frame, the scrollport and the header their styles. Runs as soon as Tabulator lays out its
195
+ * columns: until then the frame takes the width of its content, which is not the width of the header.
196
+ */
197
+ private prepareFrame;
198
+ /**
199
+ * `setData` replaces the rows only once its debounce runs out, and Tabulator emits `dataLoaded` just
200
+ * before it does. Until then, the old rows stay on the page with their hover and focus.
201
+ */
202
+ private handleDataLoaded;
203
+ /**
204
+ * Every `setColumns` builds the columns again from the definitions: Tabulator calls it as it builds,
205
+ * before `tableBuilt`. `cx-table` calls it again from its own `tableBuilt` handler, after this
206
+ * component's has run, and for every new column set.
207
+ */
208
+ private handleColumnsLoaded;
209
+ willUpdate(changedProperties: PropertyValues<this>): void;
210
+ /**
211
+ * The new saved widths replace all the widths in memory: a width that the new map does not hold,
212
+ * for example one of another site, goes away. Only a positive width counts: a bad entry has no effect.
213
+ */
214
+ private applySavedWidths;
215
+ /**
216
+ * Through Tabulator's own column visibility: new definitions would reach it through `setColumns`,
217
+ * and the rows would have to be rebuilt, which scrolls back to the top.
218
+ */
219
+ private applyHiddenFields;
220
+ updated(changedProperties: PropertyValues<this>): void;
221
+ /** Once `cx-table` has taken the new column definitions. */
222
+ private rebuildRows;
223
+ handleAssetsChange(previous?: unknown): void;
224
+ handleLoadingChange(): Promise<void>;
225
+ handleSelectedAssetIdChange(previous?: unknown): void;
226
+ handleBusyAssetIdChange(previous?: unknown): void;
227
+ handleCtaTextChange(): void;
228
+ private readonly handleNoHoverChange;
229
+ /** In place, as a relabel is: a CTA built again would drop the keyboard focus the old one held. */
230
+ private setNoHover;
231
+ connectedCallback(): void;
232
+ disconnectedCallback(): void;
233
+ private handleResize;
234
+ /**
235
+ * A new container width changes the space that the auto-fit shares out, so the columns are laid
236
+ * out again. `cx-table` renders its rows again for a new container height only until the first drag
237
+ * of a column divider, so a new height redraws the rows, which leaves no blank area under them.
238
+ */
239
+ private refitToContainer;
240
+ private readonly debouncedRedrawTable;
241
+ private readonly debouncedCalculatePageSize;
242
+ private calculatePageSize;
243
+ /** Counts the rows the last measured height shows, and tells the host when the count changes. */
244
+ private reportRowCount;
245
+ /**
246
+ * Only once the restarted rows are in: the host asks for the next page at once, and a page that
247
+ * lands while `setData` waits replaces the rows again and holds them back for another half second.
248
+ * A measurement still in its debounce reports in the same count, because a second count inside the
249
+ * host's 200 ms fetch debounce cancels the page the first count asked for.
250
+ */
251
+ private reportRestartedRowCount;
252
+ /**
253
+ * Once the load ends and any rows it brings are in, the count measured meanwhile can ask for the
254
+ * page after it. A table that is not built yet reports it at once.
255
+ */
256
+ private reportHeldRowCount;
257
+ /**
258
+ * The rows never size the container (see the styles), so this is the height the host gives the
259
+ * picker, and it can run past the viewport. No scrollport shows more rows than the viewport, so
260
+ * while the rows do not overflow the scrollport the count stops there, and the page scrolls to the
261
+ * rest, where the last row coming into view asks for more (`observeLastRow`). One that overflows,
262
+ * or holds no rows yet, measures the space its container gives it and is used as is.
263
+ */
264
+ private resolveVisibleHeight;
265
+ private isSizedByRows;
266
+ /**
267
+ * A scrollport that holds its rows without overflowing never scrolls, so its own scroll never
268
+ * reaches the end: the page scrolls instead. Once the table is taller than the viewport its count
269
+ * is capped and stops fetching, which leaves the last row coming into view as the only sign the
270
+ * user wants more.
271
+ */
272
+ private observeLastRow;
273
+ private readonly debouncedHandleLastRowVisible;
274
+ private handleLastRowVisible;
275
+ private insertAsset;
276
+ /** The host field of a row key, or `undefined` for the filler. */
277
+ private fieldOfKey;
278
+ private handleColumnResized;
279
+ /**
280
+ * Holds each other visible auto-fit column at its width when the drag ends, for the session. A drag
281
+ * on one column must not change the width of another column (L-42CA9K issue 2).
282
+ */
283
+ private holdOtherAutoFitWidths;
284
+ /**
285
+ * A double click on a column divider removes the saved width, and the column auto-fits again. The
286
+ * listener runs in the capture phase, before the listener of the divider, so the Tabulator fit to
287
+ * the content does not run.
288
+ */
289
+ private readonly handleResizeHandleDoubleClick;
290
+ private handleScrollVertical;
291
+ private readonly debouncedHandleScrollEnd;
292
+ private handleScrollEnd;
293
+ private handleRetry;
294
+ private renderRetry;
295
+ private renderContent;
296
+ render(): import("lit-html").TemplateResult<1>;
297
+ }
298
+ declare global {
299
+ interface HTMLElementTagNameMap {
300
+ 'cx-content-browser-table': CxContentBrowserTable;
301
+ }
302
+ }