@ai-matrx/design-system 0.49.23 → 0.49.25

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,7 +1,7 @@
1
1
  import * as React from 'react';
2
2
  import { ReactNode } from 'react';
3
- import { h as MatrxDataTableProps, i as TableViewSnapshot, d as MatrxDataTableRecordControls, j as MatrxDataTableRead, k as ColumnMarker, M as MatrxColumnDef } from '../layered-filters-DZNCPJsU.cjs';
4
- export { A as AnyOfColumnSearch, l as CellEditType, m as CellEditsMap, f as ColumnFilterKind, a as ColumnFilterValue, C as ColumnFiltersState, n as MatrxDataTableContextMenuConfig, g as MatrxDataTableCopyConfig, o as MatrxDataTableCoverageConfig, c as MatrxDataTableDensity, p as MatrxDataTableDetailConfig, q as MatrxDataTableEditConfig, r as MatrxDataTableEmptyState, s as MatrxDataTableExpandedDetailConfig, t as MatrxDataTableFacetsConfig, u as MatrxDataTableFilterUi, v as MatrxDataTableGroupingConfig, w as MatrxDataTableHierarchyConfig, x as MatrxDataTableHierarchyMove, y as MatrxDataTableMobileCardControls, z as MatrxDataTableMultiExpandedDetailConfig, B as MatrxDataTableQueryControl, e as MatrxDataTableQueryState, D as MatrxDataTableReadStatus, E as MatrxDataTableSelectionConfig, F as MatrxDataTableSingleExpandedDetailConfig, G as MatrxDataTableSourceProcessing, H as MatrxDataTableSpreadsheetConfig, I as MatrxDataTableStyleConfig, J as MatrxDataTableSummaryConfig, K as MatrxDataTableSummaryContext, N as MatrxDataTableSummaryMetric, O as MatrxDataTableToolbar, P as MatrxDataTableUrlStateConfig, Q as MatrxDataTableVirtualizeConfig, R as MatrxDataTableWindowConfig, U as MatrxTablePagination, V as NumberFilterOp, W as SavedTableViewTab, X as SortDirection, S as SortState, Y as SpreadsheetSelection, Z as TableRankedSearchOptions, b as TableSavedViewsProps, T as TableSearchMatchMode, _ as TableSearchRole, $ as TableSearchScope, a0 as TableViewQuery, a1 as TableViewTab, a2 as TableViewTabs, a3 as TableViewTabsProps, a4 as TableViewTabsStore, a5 as TextFilterMode, a6 as ToolbarFacet, a7 as inferTableSearchRole, a8 as rankTableSearchRows, a9 as resolveTableSearchScopes } from '../layered-filters-DZNCPJsU.cjs';
3
+ import { h as MatrxDataTableProps, i as TableViewSnapshot, d as MatrxDataTableRecordControls, j as MatrxDataTableRead, k as ColumnMarker, M as MatrxColumnDef } from '../layered-filters-frtWJUl5.cjs';
4
+ export { A as AnyOfColumnSearch, l as CellEditType, m as CellEditsMap, f as ColumnFilterKind, a as ColumnFilterValue, C as ColumnFiltersState, n as MatrxDataTableContextMenuConfig, g as MatrxDataTableCopyConfig, o as MatrxDataTableCoverageConfig, c as MatrxDataTableDensity, p as MatrxDataTableDetailConfig, q as MatrxDataTableEditConfig, r as MatrxDataTableEmptyState, s as MatrxDataTableExpandedDetailConfig, t as MatrxDataTableFacetsConfig, u as MatrxDataTableFilterUi, v as MatrxDataTableGroupingConfig, w as MatrxDataTableHierarchyConfig, x as MatrxDataTableHierarchyMove, y as MatrxDataTableMobileCardControls, z as MatrxDataTableMultiExpandedDetailConfig, B as MatrxDataTableQueryControl, e as MatrxDataTableQueryState, D as MatrxDataTableReadStatus, E as MatrxDataTableSelectionConfig, F as MatrxDataTableSingleExpandedDetailConfig, G as MatrxDataTableSourceProcessing, H as MatrxDataTableSpreadsheetConfig, I as MatrxDataTableStyleConfig, J as MatrxDataTableSummaryConfig, K as MatrxDataTableSummaryContext, N as MatrxDataTableSummaryMetric, O as MatrxDataTableToolbar, P as MatrxDataTableUrlStateConfig, Q as MatrxDataTableVirtualizeConfig, R as MatrxDataTableWindowConfig, U as MatrxTablePagination, V as NumberFilterOp, W as SavedTableViewTab, X as SortDirection, S as SortState, Y as SpreadsheetSelection, Z as TableRankedSearchOptions, b as TableSavedViewsProps, T as TableSearchMatchMode, _ as TableSearchRole, $ as TableSearchScope, a0 as TableViewQuery, a1 as TableViewTab, a2 as TableViewTabs, a3 as TableViewTabsProps, a4 as TableViewTabsStore, a5 as TextFilterMode, a6 as ToolbarFacet, a7 as inferTableSearchRole, a8 as rankTableSearchRows, a9 as resolveTableSearchScopes } from '../layered-filters-frtWJUl5.cjs';
5
5
  import { TableReadFailureProps, TableStaleNoticeProps } from './host.cjs';
6
6
  export { MatrxDataTableHost, MatrxDataTableProvider, MatrxTableRowAlchemy, TableContextMenuBoundaryProps, TableDoors, TableEntityRefProps, TableLinkProps, TableMenuIconProps, TablePeekProps, TableSidePanelProps, TableToolbarActionProps, TableWindowPanelProps, useMatrxDataTableHost, useMatrxTableRowAlchemy } from './host.cjs';
7
7
  import { CopyControlProps } from './copy-types.cjs';
@@ -85,10 +85,12 @@ interface SavedViewsControlProps {
85
85
  /** Tabs and the menu are two presentations of the same durable views. */
86
86
  presentation?: "menu" | "tabs";
87
87
  onRename?: (id: string, name: string) => void | Promise<void>;
88
+ /** Archives one durable view after confirmation; the host also resets an active view on success. */
89
+ onRemove?: (id: string) => void | Promise<void>;
88
90
  related?: ReactNode;
89
91
  }
90
92
  /** Shared named-view chooser. Persistence, authorization and validation stay host-side. */
91
- declare function SavedViewsControl({ views, activeId, loading, error, dirty, onSelect, onSaveNew, onUpdate, onReload, presentation, onRename, related, }: SavedViewsControlProps): React.JSX.Element;
93
+ declare function SavedViewsControl({ views, activeId, loading, error, dirty, onSelect, onSaveNew, onUpdate, onReload, presentation, onRename, onRemove, related, }: SavedViewsControlProps): React.JSX.Element;
92
94
 
93
95
  /** Defensive decoder for persisted JSON. Invalid snapshots are ignored by adapters. */
94
96
  declare function parseTableViewSnapshot(raw: unknown): TableViewSnapshot | null;
@@ -1,7 +1,7 @@
1
1
  import * as React from 'react';
2
2
  import { ReactNode } from 'react';
3
- import { h as MatrxDataTableProps, i as TableViewSnapshot, d as MatrxDataTableRecordControls, j as MatrxDataTableRead, k as ColumnMarker, M as MatrxColumnDef } from '../layered-filters-LwqRKKni.js';
4
- export { A as AnyOfColumnSearch, l as CellEditType, m as CellEditsMap, f as ColumnFilterKind, a as ColumnFilterValue, C as ColumnFiltersState, n as MatrxDataTableContextMenuConfig, g as MatrxDataTableCopyConfig, o as MatrxDataTableCoverageConfig, c as MatrxDataTableDensity, p as MatrxDataTableDetailConfig, q as MatrxDataTableEditConfig, r as MatrxDataTableEmptyState, s as MatrxDataTableExpandedDetailConfig, t as MatrxDataTableFacetsConfig, u as MatrxDataTableFilterUi, v as MatrxDataTableGroupingConfig, w as MatrxDataTableHierarchyConfig, x as MatrxDataTableHierarchyMove, y as MatrxDataTableMobileCardControls, z as MatrxDataTableMultiExpandedDetailConfig, B as MatrxDataTableQueryControl, e as MatrxDataTableQueryState, D as MatrxDataTableReadStatus, E as MatrxDataTableSelectionConfig, F as MatrxDataTableSingleExpandedDetailConfig, G as MatrxDataTableSourceProcessing, H as MatrxDataTableSpreadsheetConfig, I as MatrxDataTableStyleConfig, J as MatrxDataTableSummaryConfig, K as MatrxDataTableSummaryContext, N as MatrxDataTableSummaryMetric, O as MatrxDataTableToolbar, P as MatrxDataTableUrlStateConfig, Q as MatrxDataTableVirtualizeConfig, R as MatrxDataTableWindowConfig, U as MatrxTablePagination, V as NumberFilterOp, W as SavedTableViewTab, X as SortDirection, S as SortState, Y as SpreadsheetSelection, Z as TableRankedSearchOptions, b as TableSavedViewsProps, T as TableSearchMatchMode, _ as TableSearchRole, $ as TableSearchScope, a0 as TableViewQuery, a1 as TableViewTab, a2 as TableViewTabs, a3 as TableViewTabsProps, a4 as TableViewTabsStore, a5 as TextFilterMode, a6 as ToolbarFacet, a7 as inferTableSearchRole, a8 as rankTableSearchRows, a9 as resolveTableSearchScopes } from '../layered-filters-LwqRKKni.js';
3
+ import { h as MatrxDataTableProps, i as TableViewSnapshot, d as MatrxDataTableRecordControls, j as MatrxDataTableRead, k as ColumnMarker, M as MatrxColumnDef } from '../layered-filters-CKS15cIc.js';
4
+ export { A as AnyOfColumnSearch, l as CellEditType, m as CellEditsMap, f as ColumnFilterKind, a as ColumnFilterValue, C as ColumnFiltersState, n as MatrxDataTableContextMenuConfig, g as MatrxDataTableCopyConfig, o as MatrxDataTableCoverageConfig, c as MatrxDataTableDensity, p as MatrxDataTableDetailConfig, q as MatrxDataTableEditConfig, r as MatrxDataTableEmptyState, s as MatrxDataTableExpandedDetailConfig, t as MatrxDataTableFacetsConfig, u as MatrxDataTableFilterUi, v as MatrxDataTableGroupingConfig, w as MatrxDataTableHierarchyConfig, x as MatrxDataTableHierarchyMove, y as MatrxDataTableMobileCardControls, z as MatrxDataTableMultiExpandedDetailConfig, B as MatrxDataTableQueryControl, e as MatrxDataTableQueryState, D as MatrxDataTableReadStatus, E as MatrxDataTableSelectionConfig, F as MatrxDataTableSingleExpandedDetailConfig, G as MatrxDataTableSourceProcessing, H as MatrxDataTableSpreadsheetConfig, I as MatrxDataTableStyleConfig, J as MatrxDataTableSummaryConfig, K as MatrxDataTableSummaryContext, N as MatrxDataTableSummaryMetric, O as MatrxDataTableToolbar, P as MatrxDataTableUrlStateConfig, Q as MatrxDataTableVirtualizeConfig, R as MatrxDataTableWindowConfig, U as MatrxTablePagination, V as NumberFilterOp, W as SavedTableViewTab, X as SortDirection, S as SortState, Y as SpreadsheetSelection, Z as TableRankedSearchOptions, b as TableSavedViewsProps, T as TableSearchMatchMode, _ as TableSearchRole, $ as TableSearchScope, a0 as TableViewQuery, a1 as TableViewTab, a2 as TableViewTabs, a3 as TableViewTabsProps, a4 as TableViewTabsStore, a5 as TextFilterMode, a6 as ToolbarFacet, a7 as inferTableSearchRole, a8 as rankTableSearchRows, a9 as resolveTableSearchScopes } from '../layered-filters-CKS15cIc.js';
5
5
  import { TableReadFailureProps, TableStaleNoticeProps } from './host.js';
6
6
  export { MatrxDataTableHost, MatrxDataTableProvider, MatrxTableRowAlchemy, TableContextMenuBoundaryProps, TableDoors, TableEntityRefProps, TableLinkProps, TableMenuIconProps, TablePeekProps, TableSidePanelProps, TableToolbarActionProps, TableWindowPanelProps, useMatrxDataTableHost, useMatrxTableRowAlchemy } from './host.js';
7
7
  import { CopyControlProps } from './copy-types.js';
@@ -85,10 +85,12 @@ interface SavedViewsControlProps {
85
85
  /** Tabs and the menu are two presentations of the same durable views. */
86
86
  presentation?: "menu" | "tabs";
87
87
  onRename?: (id: string, name: string) => void | Promise<void>;
88
+ /** Archives one durable view after confirmation; the host also resets an active view on success. */
89
+ onRemove?: (id: string) => void | Promise<void>;
88
90
  related?: ReactNode;
89
91
  }
90
92
  /** Shared named-view chooser. Persistence, authorization and validation stay host-side. */
91
- declare function SavedViewsControl({ views, activeId, loading, error, dirty, onSelect, onSaveNew, onUpdate, onReload, presentation, onRename, related, }: SavedViewsControlProps): React.JSX.Element;
93
+ declare function SavedViewsControl({ views, activeId, loading, error, dirty, onSelect, onSaveNew, onUpdate, onReload, presentation, onRename, onRemove, related, }: SavedViewsControlProps): React.JSX.Element;
92
94
 
93
95
  /** Defensive decoder for persisted JSON. Invalid snapshots are ignored by adapters. */
94
96
  declare function parseTableViewSnapshot(raw: unknown): TableViewSnapshot | null;
@@ -36840,7 +36840,7 @@ function GenericTablePagination({
36840
36840
  // src/data-table/TableViewTabs.tsx
36841
36841
  import { useEffect as useEffect6, useRef as useRef6, useState as useState8 } from "react";
36842
36842
  import { jsx as jsx24, jsxs as jsxs16 } from "react/jsx-runtime";
36843
- function TableViewTabs({ tabs, activeId, onSelect, onAdd, onClose, onRename, related, editingId, onEditCancel, onEditDone, closable = true, addHint = "New view from the current one \xB7 double-click a tab to rename", renameable = true }) {
36843
+ function TableViewTabs({ tabs, activeId, onSelect, onAdd, onClose, onRename, related, editingId, onEditCancel, onEditDone, closable = true, closeLabel = "Close", addHint = "New view from the current one \xB7 double-click a tab to rename", renameable = true }) {
36844
36844
  const [renaming, setRenaming] = useState8(null);
36845
36845
  const [draft, setDraft] = useState8("");
36846
36846
  const opened = useRef6(null);
@@ -36929,9 +36929,9 @@ function TableViewTabs({ tabs, activeId, onSelect, onAdd, onClose, onRename, rel
36929
36929
  canClose(tab.id) && /* @__PURE__ */ jsxs16(Tooltip, { children: [
36930
36930
  /* @__PURE__ */ jsx24(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsx24("button", { type: "button", "aria-hidden": "true", tabIndex: -1, "data-close-tab": tab.id, onClick: () => onClose(tab.id), className: "flex size-7 items-center justify-center rounded hover:bg-muted", children: /* @__PURE__ */ jsx24(X, { className: "size-4" }) }) }),
36931
36931
  /* @__PURE__ */ jsxs16(TooltipContent, { children: [
36932
- "Close ",
36933
- tab.label,
36934
- " (Delete)"
36932
+ closeLabel,
36933
+ " ",
36934
+ tab.label
36935
36935
  ] })
36936
36936
  ] })
36937
36937
  ] }, tab.id)) }),
@@ -51450,6 +51450,7 @@ function MatrxDataTableCore(coreProps) {
51450
51450
  sort
51451
51451
  ]
51452
51452
  );
51453
+ const declaredDefaultSort = urlState ? urlState.defaultSort ?? null : defaultSort;
51453
51454
  const declaredDefaultViewSnapshot = useMemo11(
51454
51455
  () => defaultViewSnapshot ?? {
51455
51456
  __kind: "matrx-table-view",
@@ -51459,14 +51460,14 @@ function MatrxDataTableCore(coreProps) {
51459
51460
  search: "",
51460
51461
  anyOf: "",
51461
51462
  columnFilters: {},
51462
- sort: defaultSort
51463
+ sort: declaredDefaultSort
51463
51464
  },
51464
51465
  columns: {
51465
51466
  order: columns.map(columnId),
51466
51467
  hidden: columns.filter((column) => column.hidden).map(columnId)
51467
51468
  }
51468
51469
  },
51469
- [columns, defaultPageSize, defaultSort, defaultViewSnapshot]
51470
+ [columns, defaultPageSize, declaredDefaultSort, defaultViewSnapshot]
51470
51471
  );
51471
51472
  const applySavedView = useCallback10(
51472
51473
  (rawSnapshot) => {
@@ -54172,14 +54173,17 @@ function SavedViewsControl({
54172
54173
  onReload,
54173
54174
  presentation = "menu",
54174
54175
  onRename,
54176
+ onRemove,
54175
54177
  related
54176
54178
  }) {
54177
54179
  const unsavedChangesId = useId4();
54178
54180
  const [saveOpen, setSaveOpen] = useState27(false);
54179
54181
  const [name, setName] = useState27("");
54180
54182
  const [saving, setSaving] = useState27(false);
54183
+ const [removing, setRemoving] = useState27(false);
54181
54184
  const [actionError, setActionError] = useState27(null);
54182
54185
  const [pendingSelect, setPendingSelect] = useState27(void 0);
54186
+ const [pendingRemove, setPendingRemove] = useState27(null);
54183
54187
  const visibleError = actionError ?? error;
54184
54188
  const select = (id) => {
54185
54189
  if (id === activeId) return;
@@ -54228,6 +54232,25 @@ function SavedViewsControl({
54228
54232
  setSaving(false);
54229
54233
  }
54230
54234
  };
54235
+ const requestRemove = (id) => {
54236
+ const view = views.find((candidate) => candidate.id === id);
54237
+ if (!view || !onRemove) return;
54238
+ setActionError(null);
54239
+ setPendingRemove({ id: view.id, name: view.name });
54240
+ };
54241
+ const remove = async () => {
54242
+ if (!pendingRemove || !onRemove) return;
54243
+ setRemoving(true);
54244
+ setActionError(null);
54245
+ try {
54246
+ await onRemove(pendingRemove.id);
54247
+ setPendingRemove(null);
54248
+ } catch (cause) {
54249
+ setActionError(cause instanceof Error ? cause.message : String(cause));
54250
+ } finally {
54251
+ setRemoving(false);
54252
+ }
54253
+ };
54231
54254
  const activeName = activeId ? views.find((view) => view.id === activeId)?.name : void 0;
54232
54255
  return /* @__PURE__ */ jsxs42("div", { className: "flex min-w-0 flex-wrap items-center gap-1", "data-matrx-table-saved-views": true, children: [
54233
54256
  presentation === "tabs" ? /* @__PURE__ */ jsxs42(Fragment13, { children: [
@@ -54241,12 +54264,12 @@ function SavedViewsControl({
54241
54264
  setActionError(null);
54242
54265
  setSaveOpen(true);
54243
54266
  },
54244
- onClose: () => {
54245
- },
54267
+ onClose: requestRemove,
54246
54268
  onRename: (id, label) => {
54247
54269
  if (onRename) void Promise.resolve(onRename(id, label)).catch((cause) => setActionError(cause instanceof Error ? cause.message : String(cause)));
54248
54270
  },
54249
- closable: false,
54271
+ closable: Boolean(onRemove),
54272
+ closeLabel: "Delete saved view",
54250
54273
  renameable: Boolean(onRename),
54251
54274
  addHint: "Save a named view to your account",
54252
54275
  related
@@ -54287,6 +54310,7 @@ function SavedViewsControl({
54287
54310
  setSaveOpen(true);
54288
54311
  }, children: "Save current view\u2026" }),
54289
54312
  activeId && onUpdate ? /* @__PURE__ */ jsx53(DropdownMenuItem, { disabled: saving, onSelect: () => void update(), children: "Update current view" }) : null,
54313
+ activeId && onRemove ? /* @__PURE__ */ jsx53(DropdownMenuItem, { disabled: saving || removing, onSelect: () => requestRemove(activeId), children: "Delete current view\u2026" }) : null,
54290
54314
  onReload ? /* @__PURE__ */ jsx53(DropdownMenuItem, { disabled: saving || loading, onSelect: () => void reload(), children: "Reload views" }) : null
54291
54315
  ] })
54292
54316
  ] }),
@@ -54294,7 +54318,7 @@ function SavedViewsControl({
54294
54318
  "This table view has unsaved changes. ",
54295
54319
  presentation === "tabs" ? onUpdate ? "Use Save changes to update it." : "Use Save as view to keep it." : "Open the view menu to save or update it."
54296
54320
  ] }) : null,
54297
- visibleError && !saveOpen ? /* @__PURE__ */ jsx53(ErrorBox, { className: "basis-full break-words text-xs text-destructive", message: visibleError, operation: "Load or save a saved view", origin: "design-system/SavedViewsControl" }) : null,
54321
+ visibleError && !saveOpen && !pendingRemove ? /* @__PURE__ */ jsx53(ErrorBox, { className: "basis-full break-words text-xs text-destructive", message: visibleError, operation: "Load or save a saved view", origin: "design-system/SavedViewsControl" }) : null,
54298
54322
  /* @__PURE__ */ jsx53(Dialog, { open: saveOpen, onOpenChange: setSaveOpen, children: /* @__PURE__ */ jsxs42(DialogContent, { children: [
54299
54323
  /* @__PURE__ */ jsx53(DialogHeader, { children: /* @__PURE__ */ jsx53(DialogTitle, { children: "Save current view" }) }),
54300
54324
  visibleError ? /* @__PURE__ */ jsx53(ErrorBox, { className: "text-sm text-destructive", message: visibleError, operation: "Save a view", origin: "design-system/SavedViewsControl" }) : null,
@@ -54308,7 +54332,7 @@ function SavedViewsControl({
54308
54332
  if (!open) setPendingSelect(void 0);
54309
54333
  }, children: /* @__PURE__ */ jsxs42(DialogContent, { children: [
54310
54334
  /* @__PURE__ */ jsx53(DialogHeader, { children: /* @__PURE__ */ jsx53(DialogTitle, { children: "Unsaved view changes" }) }),
54311
- /* @__PURE__ */ jsx53("p", { className: "text-sm text-muted-foreground", children: "Switching views will discard the changes you have not saved." }),
54335
+ /* @__PURE__ */ jsx53(DialogDescription, { children: "Switching views will discard the changes you have not saved." }),
54312
54336
  /* @__PURE__ */ jsxs42(DialogFooter, { children: [
54313
54337
  /* @__PURE__ */ jsx53(Button, { type: "button", variant: "outline", onClick: () => setPendingSelect(void 0), children: "Stay on this view" }),
54314
54338
  /* @__PURE__ */ jsx53(Button, { type: "button", onClick: () => {
@@ -54317,6 +54341,25 @@ function SavedViewsControl({
54317
54341
  if (next !== void 0) onSelect(next);
54318
54342
  }, children: "Discard changes and switch" })
54319
54343
  ] })
54344
+ ] }) }),
54345
+ /* @__PURE__ */ jsx53(Dialog, { open: pendingRemove !== null, onOpenChange: (open) => {
54346
+ if (!open && !removing) setPendingRemove(null);
54347
+ }, children: /* @__PURE__ */ jsxs42(DialogContent, { children: [
54348
+ /* @__PURE__ */ jsx53(DialogHeader, { children: /* @__PURE__ */ jsxs42(DialogTitle, { children: [
54349
+ "Delete ",
54350
+ pendingRemove ? `\u201C${pendingRemove.name}\u201D` : "saved view",
54351
+ "?"
54352
+ ] }) }),
54353
+ actionError ? /* @__PURE__ */ jsx53(ErrorBox, { className: "text-sm text-destructive", message: actionError, operation: "Delete a saved view", origin: "design-system/SavedViewsControl" }) : null,
54354
+ /* @__PURE__ */ jsxs42(DialogDescription, { children: [
54355
+ "This removes the saved view from your account",
54356
+ activeId === pendingRemove?.id && dirty ? " and discards its unsaved layout changes" : "",
54357
+ "."
54358
+ ] }),
54359
+ /* @__PURE__ */ jsxs42(DialogFooter, { children: [
54360
+ /* @__PURE__ */ jsx53(Button, { type: "button", variant: "outline", disabled: removing, onClick: () => setPendingRemove(null), children: "Cancel" }),
54361
+ /* @__PURE__ */ jsx53(Button, { type: "button", variant: "destructive", disabled: removing, onClick: () => void remove(), children: removing ? "Deleting\u2026" : "Delete view" })
54362
+ ] })
54320
54363
  ] }) })
54321
54364
  ] });
54322
54365
  }