@planningcenter/tapestry 4.12.0 → 4.13.0-rc.0

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 (134) hide show
  1. package/dist/componentRegistrars.d.ts +1 -0
  2. package/dist/componentRegistrars.d.ts.map +1 -1
  3. package/dist/componentRegistrars.js +6 -2
  4. package/dist/componentRegistrars.js.map +1 -1
  5. package/dist/components/DataTable/ActiveFilters.d.ts +23 -1
  6. package/dist/components/DataTable/ActiveFilters.d.ts.map +1 -1
  7. package/dist/components/DataTable/ActiveFilters.js +49 -4
  8. package/dist/components/DataTable/ActiveFilters.js.map +1 -1
  9. package/dist/components/DataTable/CollectionEditorsLazy.d.ts.map +1 -1
  10. package/dist/components/DataTable/CollectionEditorsLazy.js +20 -18
  11. package/dist/components/DataTable/CollectionEditorsLazy.js.map +1 -1
  12. package/dist/components/DataTable/DataTable.d.ts +66 -50
  13. package/dist/components/DataTable/DataTable.d.ts.map +1 -1
  14. package/dist/components/DataTable/DataTable.js +78 -17
  15. package/dist/components/DataTable/DataTable.js.map +1 -1
  16. package/dist/components/DataTable/ManageSavedViewsModal.d.ts +18 -7
  17. package/dist/components/DataTable/ManageSavedViewsModal.d.ts.map +1 -1
  18. package/dist/components/DataTable/ManageSavedViewsModal.js +120 -104
  19. package/dist/components/DataTable/ManageSavedViewsModal.js.map +1 -1
  20. package/dist/components/DataTable/ManageSavedViewsModal.module.css.js +1 -1
  21. package/dist/components/DataTable/NewSavedViewButton.d.ts.map +1 -1
  22. package/dist/components/DataTable/NewSavedViewButton.js +1 -1
  23. package/dist/components/DataTable/NewSavedViewButton.js.map +1 -1
  24. package/dist/components/DataTable/SavedViewActions.d.ts +19 -0
  25. package/dist/components/DataTable/SavedViewActions.d.ts.map +1 -0
  26. package/dist/components/DataTable/SavedViewActions.js +34 -0
  27. package/dist/components/DataTable/SavedViewActions.js.map +1 -0
  28. package/dist/components/DataTable/SavedViewMenu.d.ts +18 -0
  29. package/dist/components/DataTable/SavedViewMenu.d.ts.map +1 -0
  30. package/dist/components/DataTable/SavedViewMenu.js +25 -0
  31. package/dist/components/DataTable/SavedViewMenu.js.map +1 -0
  32. package/dist/components/DataTable/SavedViewsBar.d.ts +25 -13
  33. package/dist/components/DataTable/SavedViewsBar.d.ts.map +1 -1
  34. package/dist/components/DataTable/SavedViewsBar.js +43 -83
  35. package/dist/components/DataTable/SavedViewsBar.js.map +1 -1
  36. package/dist/components/DataTable/TableActions.d.ts +4 -2
  37. package/dist/components/DataTable/TableActions.d.ts.map +1 -1
  38. package/dist/components/DataTable/TableActions.js +11 -14
  39. package/dist/components/DataTable/TableActions.js.map +1 -1
  40. package/dist/components/DataTable/index.d.ts +2 -0
  41. package/dist/components/DataTable/index.d.ts.map +1 -1
  42. package/dist/components/DataTable/saveErrorMessage.d.ts +3 -0
  43. package/dist/components/DataTable/saveErrorMessage.d.ts.map +1 -0
  44. package/dist/components/DataTable/saveErrorMessage.js +9 -0
  45. package/dist/components/DataTable/saveErrorMessage.js.map +1 -0
  46. package/dist/components/DataTable/savedViews.d.ts +15 -30
  47. package/dist/components/DataTable/savedViews.d.ts.map +1 -1
  48. package/dist/components/DataTable/savedViews.js +51 -98
  49. package/dist/components/DataTable/savedViews.js.map +1 -1
  50. package/dist/components/DataTable/useActiveSavedView.d.ts +1 -1
  51. package/dist/components/DataTable/useActiveSavedView.d.ts.map +1 -1
  52. package/dist/components/DataTable/useActiveSavedView.js +5 -4
  53. package/dist/components/DataTable/useActiveSavedView.js.map +1 -1
  54. package/dist/components/DataTable/useColumnVisibility.d.ts +7 -7
  55. package/dist/components/DataTable/useColumnVisibility.d.ts.map +1 -1
  56. package/dist/components/DataTable/useColumnVisibility.js +14 -14
  57. package/dist/components/DataTable/useColumnVisibility.js.map +1 -1
  58. package/dist/components/DataTable/useResultsAnnouncement.d.ts +26 -0
  59. package/dist/components/DataTable/useResultsAnnouncement.d.ts.map +1 -0
  60. package/dist/components/DataTable/{useFilterAnnouncement.js → useResultsAnnouncement.js} +16 -12
  61. package/dist/components/DataTable/useResultsAnnouncement.js.map +1 -0
  62. package/dist/components/DataTable/useSaveStatus.d.ts +32 -0
  63. package/dist/components/DataTable/useSaveStatus.d.ts.map +1 -0
  64. package/dist/components/DataTable/useSaveStatus.js +80 -0
  65. package/dist/components/DataTable/useSaveStatus.js.map +1 -0
  66. package/dist/components/DataTable/useSavedViewNameModal.d.ts +14 -0
  67. package/dist/components/DataTable/useSavedViewNameModal.d.ts.map +1 -0
  68. package/dist/components/DataTable/useSavedViewNameModal.js +43 -0
  69. package/dist/components/DataTable/useSavedViewNameModal.js.map +1 -0
  70. package/dist/components/DataTable/useSavedViewsClient.d.ts +58 -0
  71. package/dist/components/DataTable/useSavedViewsClient.d.ts.map +1 -0
  72. package/dist/components/DataTable/useSavedViewsClient.js +87 -0
  73. package/dist/components/DataTable/useSavedViewsClient.js.map +1 -0
  74. package/dist/components/DataTable/useSavedViewsState.d.ts +35 -0
  75. package/dist/components/DataTable/useSavedViewsState.d.ts.map +1 -0
  76. package/dist/components/DataTable/useSavedViewsState.js +192 -0
  77. package/dist/components/DataTable/useSavedViewsState.js.map +1 -0
  78. package/dist/components/DataTable/useUpdateSavedViewName.d.ts +2 -3
  79. package/dist/components/DataTable/useUpdateSavedViewName.d.ts.map +1 -1
  80. package/dist/components/DataTable/useUpdateSavedViewName.js +1 -2
  81. package/dist/components/DataTable/useUpdateSavedViewName.js.map +1 -1
  82. package/dist/components/button/BaseButton.d.ts +2 -0
  83. package/dist/components/button/BaseButton.d.ts.map +1 -1
  84. package/dist/components/button/BaseButton.js +8 -17
  85. package/dist/components/button/BaseButton.js.map +1 -1
  86. package/dist/components/internal/LoadingAnnouncement.d.ts +6 -0
  87. package/dist/components/internal/LoadingAnnouncement.d.ts.map +1 -1
  88. package/dist/components/internal/LoadingAnnouncement.js +12 -3
  89. package/dist/components/internal/LoadingAnnouncement.js.map +1 -1
  90. package/dist/components/internal/index.d.ts +1 -1
  91. package/dist/components/internal/index.d.ts.map +1 -1
  92. package/dist/components/internal/tooltip/useTooltipTriggerProps.d.ts +13 -0
  93. package/dist/components/internal/tooltip/useTooltipTriggerProps.d.ts.map +1 -0
  94. package/dist/components/internal/tooltip/useTooltipTriggerProps.js +24 -0
  95. package/dist/components/internal/tooltip/useTooltipTriggerProps.js.map +1 -0
  96. package/dist/components/link/BaseLink.d.ts.map +1 -1
  97. package/dist/components/link/BaseLink.js +3 -13
  98. package/dist/components/link/BaseLink.js.map +1 -1
  99. package/dist/components/segmented-control/IconSegment.d.ts +30 -8
  100. package/dist/components/segmented-control/IconSegment.d.ts.map +1 -1
  101. package/dist/components/segmented-control/IconSegment.js +10 -3
  102. package/dist/components/segmented-control/IconSegment.js.map +1 -1
  103. package/dist/components/segmented-control/SegmentBase.d.ts.map +1 -1
  104. package/dist/components/segmented-control/SegmentBase.js +4 -2
  105. package/dist/components/segmented-control/SegmentBase.js.map +1 -1
  106. package/dist/components/segmented-control/SegmentedControl.d.ts.map +1 -1
  107. package/dist/components/segmented-control/SegmentedControl.js +10 -3
  108. package/dist/components/segmented-control/SegmentedControl.js.map +1 -1
  109. package/dist/index.css +20 -5
  110. package/dist/index.css.map +1 -1
  111. package/dist/reactRender.css +1409 -1319
  112. package/dist/reactRender.css.map +1 -1
  113. package/dist/reactRender.js +1 -1
  114. package/dist/reactRenderLegacy.css +1409 -1319
  115. package/dist/reactRenderLegacy.css.map +1 -1
  116. package/dist/reactRenderLegacy.js +1 -1
  117. package/dist/tapestryMount.css +1409 -1319
  118. package/dist/tapestryMount.css.map +1 -1
  119. package/dist/tapestryMount.js +1 -1
  120. package/dist/tapestryMountLegacy.css +1409 -1319
  121. package/dist/tapestryMountLegacy.css.map +1 -1
  122. package/dist/tapestryMountLegacy.js +1 -1
  123. package/dist/tokens-dark.css +2 -2
  124. package/dist/tokens-dark.css.map +1 -1
  125. package/dist/tokens.css +3 -3
  126. package/dist/tokens.css.map +1 -1
  127. package/dist/unstable.css +385 -295
  128. package/dist/unstable.css.map +1 -1
  129. package/dist/unstable.js +1 -0
  130. package/dist/unstable.js.map +1 -1
  131. package/package.json +6 -7
  132. package/dist/components/DataTable/useFilterAnnouncement.d.ts +0 -24
  133. package/dist/components/DataTable/useFilterAnnouncement.d.ts.map +0 -1
  134. package/dist/components/DataTable/useFilterAnnouncement.js.map +0 -1
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SavedViewActions.js","sources":["../../../src/components/DataTable/SavedViewActions.tsx"],"sourcesContent":["import { Button, IconButton } from \"@components/button\"\nimport { ButtonGroup } from \"@components/button-group\"\nimport {\n Dropdown,\n DropdownAction,\n DropdownMenu,\n DropdownTrigger,\n} from \"@components/dropdown\"\nimport Icon from \"@utilities/Icon\"\nimport React, { useState } from \"react\"\n\nimport { NewSavedViewModal } from \"./NewSavedViewModal\"\n\nexport interface SavedViewActionsProps {\n onDiscard: () => void\n /** Omit to hide \"Save as new view\". */\n onSaveAsNew?: (name: string) => void\n /** Omit to disable \"Update view\". */\n onUpdate?: () => void\n /** The view whose filters have changed. */\n savedViewName: string\n}\n\n/**\n * Actions for a modified saved view. The host owns focus afterward, since it\n * decides whether these stay mounted.\n */\nexport function SavedViewActions({\n onDiscard,\n onSaveAsNew,\n onUpdate,\n savedViewName,\n}: SavedViewActionsProps) {\n const [isNewViewModalOpen, setIsNewViewModalOpen] = useState(false)\n\n return (\n <>\n <ButtonGroup aria-label={`Changes to ${savedViewName}`}>\n <Button\n disabled={!onUpdate}\n kind=\"secondary\"\n label=\"Update view\"\n size=\"sm\"\n onClick={onUpdate}\n />\n <Dropdown>\n <DropdownTrigger>\n <IconButton\n aria-label=\"More view actions\"\n icon={<Icon aria-hidden symbol=\"general#down-caret\" />}\n kind=\"secondary\"\n size=\"sm\"\n />\n </DropdownTrigger>\n <DropdownMenu placement=\"bottom end\">\n {onSaveAsNew && (\n <DropdownAction\n id=\"save-as-new\"\n onAction={() =>\n queueMicrotask(() => setIsNewViewModalOpen(true))\n }\n >\n Save as new view\n </DropdownAction>\n )}\n <DropdownAction id=\"discard\" onAction={onDiscard}>\n Discard changes\n </DropdownAction>\n </DropdownMenu>\n </Dropdown>\n </ButtonGroup>\n {onSaveAsNew && (\n <NewSavedViewModal\n open={isNewViewModalOpen}\n onClose={() => setIsNewViewModalOpen(false)}\n onSave={onSaveAsNew}\n />\n )}\n </>\n )\n}\n\nSavedViewActions.displayName = \"SavedViewActions\"\n"],"names":["React"],"mappings":";;;;;;;;;;;;;AAuBA;;;AAGG;AACG,SAAU,gBAAgB,CAAC,EAC/B,SAAS,EACT,WAAW,EACX,QAAQ,EACR,aAAa,GACS,EAAA;IACtB,MAAM,CAAC,kBAAkB,EAAE,qBAAqB,CAAC,GAAG,QAAQ,CAAC,KAAK,CAAC;AAEnE,IAAA,QACEA,cAAA,CAAA,aAAA,CAAAA,cAAA,CAAA,QAAA,EAAA,IAAA;AACE,QAAAA,cAAA,CAAA,aAAA,CAAC,WAAW,EAAA,EAAA,YAAA,EAAa,CAAA,WAAA,EAAc,aAAa,CAAA,CAAE,EAAA;YACpDA,cAAA,CAAA,aAAA,CAAC,MAAM,IACL,QAAQ,EAAE,CAAC,QAAQ,EACnB,IAAI,EAAC,WAAW,EAChB,KAAK,EAAC,aAAa,EACnB,IAAI,EAAC,IAAI,EACT,OAAO,EAAE,QAAQ,EAAA,CACjB;AACF,YAAAA,cAAA,CAAA,aAAA,CAAC,QAAQ,EAAA,IAAA;AACP,gBAAAA,cAAA,CAAA,aAAA,CAAC,eAAe,EAAA,IAAA;oBACdA,cAAA,CAAA,aAAA,CAAC,UAAU,kBACE,mBAAmB,EAC9B,IAAI,EAAEA,cAAA,CAAA,aAAA,CAAC,IAAI,EAAA,EAAA,aAAA,EAAA,IAAA,EAAa,MAAM,EAAC,oBAAoB,EAAA,CAAG,EACtD,IAAI,EAAC,WAAW,EAChB,IAAI,EAAC,IAAI,EAAA,CACT,CACc;AAClB,gBAAAA,cAAA,CAAA,aAAA,CAAC,YAAY,EAAA,EAAC,SAAS,EAAC,YAAY,EAAA;oBACjC,WAAW,KACVA,cAAA,CAAA,aAAA,CAAC,cAAc,EAAA,EACb,EAAE,EAAC,aAAa,EAChB,QAAQ,EAAE,MACR,cAAc,CAAC,MAAM,qBAAqB,CAAC,IAAI,CAAC,CAAC,EAAA,EAAA,kBAAA,CAIpC,CAClB;AACD,oBAAAA,cAAA,CAAA,aAAA,CAAC,cAAc,EAAA,EAAC,EAAE,EAAC,SAAS,EAAC,QAAQ,EAAE,SAAS,EAAA,EAAA,iBAAA,CAE/B,CACJ,CACN,CACC;QACb,WAAW,KACVA,cAAA,CAAA,aAAA,CAAC,iBAAiB,EAAA,EAChB,IAAI,EAAE,kBAAkB,EACxB,OAAO,EAAE,MAAM,qBAAqB,CAAC,KAAK,CAAC,EAC3C,MAAM,EAAE,WAAW,EAAA,CACnB,CACH,CACA;AAEP;AAEA,gBAAgB,CAAC,WAAW,GAAG,kBAAkB;;;;"}
@@ -0,0 +1,18 @@
1
+ import { type DropdownPlacement } from "../dropdown";
2
+ import React from "react";
3
+ export interface SavedViewMenuProps {
4
+ isDefault: boolean;
5
+ /** Omit to leave out each action. */
6
+ onDelete?: () => void;
7
+ onDuplicate?: () => void;
8
+ onRename?: () => void;
9
+ onSetDefault?: () => void;
10
+ placement?: DropdownPlacement;
11
+ }
12
+ /**
13
+ * A view's actions, shared by its context menu in the bar and its actions
14
+ * menu in Manage views. Render it only when `hasSavedViewMenuActions`.
15
+ */
16
+ export declare function SavedViewMenu({ isDefault, onDelete, onDuplicate, onRename, onSetDefault, placement, }: SavedViewMenuProps): React.JSX.Element;
17
+ export declare function hasSavedViewMenuActions({ onDelete, onDuplicate, onRename, onSetDefault, }: SavedViewMenuProps): boolean;
18
+ //# sourceMappingURL=SavedViewMenu.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SavedViewMenu.d.ts","sourceRoot":"","sources":["../../../src/components/DataTable/SavedViewMenu.tsx"],"names":[],"mappings":"AAAA,OAAO,EAGL,KAAK,iBAAiB,EAEvB,MAAM,sBAAsB,CAAA;AAC7B,OAAO,KAAK,MAAM,OAAO,CAAA;AAEzB,MAAM,WAAW,kBAAkB;IACjC,SAAS,EAAE,OAAO,CAAA;IAClB,qCAAqC;IACrC,QAAQ,CAAC,EAAE,MAAM,IAAI,CAAA;IACrB,WAAW,CAAC,EAAE,MAAM,IAAI,CAAA;IACxB,QAAQ,CAAC,EAAE,MAAM,IAAI,CAAA;IACrB,YAAY,CAAC,EAAE,MAAM,IAAI,CAAA;IACzB,SAAS,CAAC,EAAE,iBAAiB,CAAA;CAC9B;AAED;;;GAGG;AACH,wBAAgB,aAAa,CAAC,EAC5B,SAAS,EACT,QAAQ,EACR,WAAW,EACX,QAAQ,EACR,YAAY,EACZ,SAAS,GACV,EAAE,kBAAkB,qBAkCpB;AAED,wBAAgB,uBAAuB,CAAC,EACtC,QAAQ,EACR,WAAW,EACX,QAAQ,EACR,YAAY,GACb,EAAE,kBAAkB,WAEpB"}
@@ -0,0 +1,25 @@
1
+ import { DropdownMenu, DropdownAction, DropdownSeparator } from '../dropdown/Dropdown.js';
2
+ import React__default from 'react';
3
+
4
+ /**
5
+ * A view's actions, shared by its context menu in the bar and its actions
6
+ * menu in Manage views. Render it only when `hasSavedViewMenuActions`.
7
+ */
8
+ function SavedViewMenu({ isDefault, onDelete, onDuplicate, onRename, onSetDefault, placement, }) {
9
+ const hasActions = Boolean(onRename || onDuplicate || onSetDefault);
10
+ return (React__default.createElement(DropdownMenu, { placement: placement },
11
+ onRename && (React__default.createElement(DropdownAction, { id: "rename", onAction: onRename }, "Rename")),
12
+ onDuplicate && (React__default.createElement(DropdownAction, { id: "duplicate", onAction: onDuplicate }, "Duplicate")),
13
+ onSetDefault && (
14
+ // Stays in the menu for the default view, disabled, so the user can
15
+ // see which view is the default.
16
+ React__default.createElement(DropdownAction, { disabled: isDefault, id: "set-default", onAction: onSetDefault }, isDefault ? "Default view" : "Set as default")),
17
+ hasActions && onDelete && React__default.createElement(DropdownSeparator, null),
18
+ onDelete && (React__default.createElement(DropdownAction, { destructive: true, id: "delete", onAction: onDelete }, "Delete"))));
19
+ }
20
+ function hasSavedViewMenuActions({ onDelete, onDuplicate, onRename, onSetDefault, }) {
21
+ return Boolean(onDelete || onDuplicate || onRename || onSetDefault);
22
+ }
23
+
24
+ export { SavedViewMenu, hasSavedViewMenuActions };
25
+ //# sourceMappingURL=SavedViewMenu.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SavedViewMenu.js","sources":["../../../src/components/DataTable/SavedViewMenu.tsx"],"sourcesContent":["import {\n DropdownAction,\n DropdownMenu,\n type DropdownPlacement,\n DropdownSeparator,\n} from \"@components/dropdown\"\nimport React from \"react\"\n\nexport interface SavedViewMenuProps {\n isDefault: boolean\n /** Omit to leave out each action. */\n onDelete?: () => void\n onDuplicate?: () => void\n onRename?: () => void\n onSetDefault?: () => void\n placement?: DropdownPlacement\n}\n\n/**\n * A view's actions, shared by its context menu in the bar and its actions\n * menu in Manage views. Render it only when `hasSavedViewMenuActions`.\n */\nexport function SavedViewMenu({\n isDefault,\n onDelete,\n onDuplicate,\n onRename,\n onSetDefault,\n placement,\n}: SavedViewMenuProps) {\n const hasActions = Boolean(onRename || onDuplicate || onSetDefault)\n\n return (\n <DropdownMenu placement={placement}>\n {onRename && (\n <DropdownAction id=\"rename\" onAction={onRename}>\n Rename\n </DropdownAction>\n )}\n {onDuplicate && (\n <DropdownAction id=\"duplicate\" onAction={onDuplicate}>\n Duplicate\n </DropdownAction>\n )}\n {onSetDefault && (\n // Stays in the menu for the default view, disabled, so the user can\n // see which view is the default.\n <DropdownAction\n disabled={isDefault}\n id=\"set-default\"\n onAction={onSetDefault}\n >\n {isDefault ? \"Default view\" : \"Set as default\"}\n </DropdownAction>\n )}\n {hasActions && onDelete && <DropdownSeparator />}\n {onDelete && (\n <DropdownAction destructive id=\"delete\" onAction={onDelete}>\n Delete\n </DropdownAction>\n )}\n </DropdownMenu>\n )\n}\n\nexport function hasSavedViewMenuActions({\n onDelete,\n onDuplicate,\n onRename,\n onSetDefault,\n}: SavedViewMenuProps) {\n return Boolean(onDelete || onDuplicate || onRename || onSetDefault)\n}\n"],"names":["React"],"mappings":";;;AAkBA;;;AAGG;AACG,SAAU,aAAa,CAAC,EAC5B,SAAS,EACT,QAAQ,EACR,WAAW,EACX,QAAQ,EACR,YAAY,EACZ,SAAS,GACU,EAAA;IACnB,MAAM,UAAU,GAAG,OAAO,CAAC,QAAQ,IAAI,WAAW,IAAI,YAAY,CAAC;AAEnE,IAAA,QACEA,cAAA,CAAA,aAAA,CAAC,YAAY,EAAA,EAAC,SAAS,EAAE,SAAS,EAAA;AAC/B,QAAA,QAAQ,KACPA,cAAA,CAAA,aAAA,CAAC,cAAc,EAAA,EAAC,EAAE,EAAC,QAAQ,EAAC,QAAQ,EAAE,QAAQ,aAE7B,CAClB;AACA,QAAA,WAAW,KACVA,cAAA,CAAA,aAAA,CAAC,cAAc,EAAA,EAAC,EAAE,EAAC,WAAW,EAAC,QAAQ,EAAE,WAAW,gBAEnC,CAClB;AACA,QAAA,YAAY;;;QAGXA,cAAA,CAAA,aAAA,CAAC,cAAc,EAAA,EACb,QAAQ,EAAE,SAAS,EACnB,EAAE,EAAC,aAAa,EAChB,QAAQ,EAAE,YAAY,EAAA,EAErB,SAAS,GAAG,cAAc,GAAG,gBAAgB,CAC/B,CAClB;AACA,QAAA,UAAU,IAAI,QAAQ,IAAIA,cAAA,CAAA,aAAA,CAAC,iBAAiB,EAAA,IAAA,CAAG;AAC/C,QAAA,QAAQ,KACPA,cAAA,CAAA,aAAA,CAAC,cAAc,EAAA,EAAC,WAAW,QAAC,EAAE,EAAC,QAAQ,EAAC,QAAQ,EAAE,QAAQ,aAEzC,CAClB,CACY;AAEnB;AAEM,SAAU,uBAAuB,CAAC,EACtC,QAAQ,EACR,WAAW,EACX,QAAQ,EACR,YAAY,GACO,EAAA;IACnB,OAAO,OAAO,CAAC,QAAQ,IAAI,WAAW,IAAI,QAAQ,IAAI,YAAY,CAAC;AACrE;;;;"}
@@ -1,31 +1,43 @@
1
1
  import React from "react";
2
- import type { Sort } from "./DataTable";
3
- import type { DataTableColumn } from "./DataTableColumn";
4
- import type { ActiveFilter } from "./FilterTypes";
5
2
  import { type SavedView, type StaticView } from "./savedViews";
3
+ import type { ReorderTarget } from "./useSavedViewsState";
4
+ import { type useSaveStatus } from "./useSaveStatus";
6
5
  export interface SavedViewsBarProps {
7
- activeFilters: ActiveFilter[];
6
+ /** The selected view, if any. */
7
+ activeSavedView: SavedView | undefined;
8
+ /** What New view saves. Its filters leave out the search. */
9
+ currentState: Omit<SavedView, "id" | "name">;
8
10
  defaultViewId: NonNullable<SavedView["id"]>;
9
- hideableColumns: DataTableColumn[];
10
- isColumnVisible: (column: DataTableColumn) => boolean;
11
+ /** Disables the drag handles while a reorder saves. */
12
+ isReordering?: boolean;
11
13
  onApply: (savedView: SavedView) => void;
12
14
  /**
13
15
  * Returns the saved view with its new id. Omit to hide the new view button
14
16
  * and the Duplicate action.
15
17
  */
16
- onCreate?: (savedView: Omit<SavedView, "id">) => Promise<SavedView> | SavedView;
18
+ onCreate?: (savedView: Omit<SavedView, "id">) => Promise<SavedView | undefined> | SavedView;
17
19
  /** Called once the user confirms. Omit to leave out the Delete action. */
18
- onDelete?: (savedView: SavedView) => void;
20
+ onDelete?: (savedView: SavedView) => Promise<void>;
21
+ /** Omit to leave out the drag handles in the manage views modal. */
22
+ onReorder?: (savedView: SavedView, target: ReorderTarget) => Promise<void>;
19
23
  /** Omit to leave out the Set as default action. */
20
- onSetDefault?: (id: NonNullable<SavedView["id"]>) => void;
24
+ onSetDefault?: (id: NonNullable<SavedView["id"]>) => Promise<void>;
21
25
  /** Omit to leave out the Rename action. */
22
- onUpdate?: (savedView: SavedView) => Promise<SavedView> | SavedView;
26
+ onUpdate?: (savedView: SavedView) => Promise<SavedView | undefined> | SavedView;
27
+ /** Tracks saves, shared with the filters shelf's saved view actions. */
28
+ saveStatus: ReturnType<typeof useSaveStatus>;
23
29
  savedViews: SavedView[];
24
- sortBy: Sort | undefined;
25
- /** Listed before `savedViews` and can't be edited. */
30
+ /** Selects the view the user picked. */
31
+ select: (savedView: SavedView) => void;
32
+ /** Selects a created view once it's saved, resolving to it if selected. */
33
+ selectWhenSaved: (savedView: Promise<SavedView | undefined> | SavedView) => Promise<SavedView | undefined>;
34
+ /**
35
+ * Listed before `savedViews` and can't be edited. Starts with the initial
36
+ * view unless one replaces it.
37
+ */
26
38
  staticViews: StaticView[];
27
39
  }
28
- export declare function SavedViewsBar({ defaultViewId, onApply, onCreate, onDelete, onSetDefault, onUpdate, savedViews, staticViews, activeFilters, hideableColumns, isColumnVisible, sortBy, }: SavedViewsBarProps): React.JSX.Element;
40
+ export declare function SavedViewsBar({ activeSavedView, currentState, defaultViewId, isReordering, onApply, onCreate, onDelete, onReorder, onSetDefault, onUpdate, saveStatus, savedViews, select, selectWhenSaved, staticViews, }: SavedViewsBarProps): React.JSX.Element;
29
41
  export declare namespace SavedViewsBar {
30
42
  var displayName: string;
31
43
  }
@@ -1 +1 @@
1
- {"version":3,"file":"SavedViewsBar.d.ts","sourceRoot":"","sources":["../../../src/components/DataTable/SavedViewsBar.tsx"],"names":[],"mappings":"AAWA,OAAO,KAaN,MAAM,OAAO,CAAA;AAId,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,aAAa,CAAA;AACvC,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAA;AAExD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,eAAe,CAAA;AAKjD,OAAO,EAGL,KAAK,SAAS,EAEd,KAAK,UAAU,EAChB,MAAM,cAAc,CAAA;AAUrB,MAAM,WAAW,kBAAkB;IACjC,aAAa,EAAE,YAAY,EAAE,CAAA;IAC7B,aAAa,EAAE,WAAW,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,CAAA;IAC3C,eAAe,EAAE,eAAe,EAAE,CAAA;IAClC,eAAe,EAAE,CAAC,MAAM,EAAE,eAAe,KAAK,OAAO,CAAA;IACrD,OAAO,EAAE,CAAC,SAAS,EAAE,SAAS,KAAK,IAAI,CAAA;IACvC;;;OAGG;IACH,QAAQ,CAAC,EAAE,CACT,SAAS,EAAE,IAAI,CAAC,SAAS,EAAE,IAAI,CAAC,KAC7B,OAAO,CAAC,SAAS,CAAC,GAAG,SAAS,CAAA;IACnC,0EAA0E;IAC1E,QAAQ,CAAC,EAAE,CAAC,SAAS,EAAE,SAAS,KAAK,IAAI,CAAA;IACzC,mDAAmD;IACnD,YAAY,CAAC,EAAE,CAAC,EAAE,EAAE,WAAW,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,KAAK,IAAI,CAAA;IACzD,2CAA2C;IAC3C,QAAQ,CAAC,EAAE,CAAC,SAAS,EAAE,SAAS,KAAK,OAAO,CAAC,SAAS,CAAC,GAAG,SAAS,CAAA;IACnE,UAAU,EAAE,SAAS,EAAE,CAAA;IACvB,MAAM,EAAE,IAAI,GAAG,SAAS,CAAA;IACxB,sDAAsD;IACtD,WAAW,EAAE,UAAU,EAAE,CAAA;CAC1B;AAED,wBAAgB,aAAa,CAAC,EAC5B,aAAa,EACb,OAAO,EACP,QAAQ,EACR,QAAQ,EACR,YAAY,EACZ,QAAQ,EACR,UAAU,EACV,WAAW,EACX,aAAa,EACb,eAAe,EACf,eAAe,EACf,MAAM,GACP,EAAE,kBAAkB,qBAiSpB;yBA9Se,aAAa"}
1
+ {"version":3,"file":"SavedViewsBar.d.ts","sourceRoot":"","sources":["../../../src/components/DataTable/SavedViewsBar.tsx"],"names":[],"mappings":"AAMA,OAAO,KAaN,MAAM,OAAO,CAAA;AAUd,OAAO,EAEL,KAAK,SAAS,EACd,KAAK,UAAU,EAChB,MAAM,cAAc,CAAA;AAErB,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAA;AACzD,OAAO,EAA4B,KAAK,aAAa,EAAE,MAAM,iBAAiB,CAAA;AAQ9E,MAAM,WAAW,kBAAkB;IACjC,iCAAiC;IACjC,eAAe,EAAE,SAAS,GAAG,SAAS,CAAA;IACtC,6DAA6D;IAC7D,YAAY,EAAE,IAAI,CAAC,SAAS,EAAE,IAAI,GAAG,MAAM,CAAC,CAAA;IAC5C,aAAa,EAAE,WAAW,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,CAAA;IAC3C,uDAAuD;IACvD,YAAY,CAAC,EAAE,OAAO,CAAA;IACtB,OAAO,EAAE,CAAC,SAAS,EAAE,SAAS,KAAK,IAAI,CAAA;IACvC;;;OAGG;IACH,QAAQ,CAAC,EAAE,CACT,SAAS,EAAE,IAAI,CAAC,SAAS,EAAE,IAAI,CAAC,KAC7B,OAAO,CAAC,SAAS,GAAG,SAAS,CAAC,GAAG,SAAS,CAAA;IAC/C,0EAA0E;IAC1E,QAAQ,CAAC,EAAE,CAAC,SAAS,EAAE,SAAS,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;IAClD,oEAAoE;IACpE,SAAS,CAAC,EAAE,CAAC,SAAS,EAAE,SAAS,EAAE,MAAM,EAAE,aAAa,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;IAC1E,mDAAmD;IACnD,YAAY,CAAC,EAAE,CAAC,EAAE,EAAE,WAAW,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;IAClE,2CAA2C;IAC3C,QAAQ,CAAC,EAAE,CACT,SAAS,EAAE,SAAS,KACjB,OAAO,CAAC,SAAS,GAAG,SAAS,CAAC,GAAG,SAAS,CAAA;IAC/C,wEAAwE;IACxE,UAAU,EAAE,UAAU,CAAC,OAAO,aAAa,CAAC,CAAA;IAC5C,UAAU,EAAE,SAAS,EAAE,CAAA;IACvB,wCAAwC;IACxC,MAAM,EAAE,CAAC,SAAS,EAAE,SAAS,KAAK,IAAI,CAAA;IACtC,2EAA2E;IAC3E,eAAe,EAAE,CACf,SAAS,EAAE,OAAO,CAAC,SAAS,GAAG,SAAS,CAAC,GAAG,SAAS,KAClD,OAAO,CAAC,SAAS,GAAG,SAAS,CAAC,CAAA;IACnC;;;OAGG;IACH,WAAW,EAAE,UAAU,EAAE,CAAA;CAC1B;AAED,wBAAgB,aAAa,CAAC,EAC5B,eAAe,EACf,YAAY,EACZ,aAAa,EACb,YAAY,EACZ,OAAO,EACP,QAAQ,EACR,QAAQ,EACR,SAAS,EACT,YAAY,EACZ,QAAQ,EACR,UAAU,EACV,UAAU,EACV,MAAM,EACN,eAAe,EACf,WAAW,GACZ,EAAE,kBAAkB,qBA4NpB;yBA5Oe,aAAa"}
@@ -1,4 +1,3 @@
1
- import { DropdownMenu, DropdownAction, DropdownSeparator } from '../dropdown/Dropdown.js';
2
1
  import { ReorderableListBox, ReorderableListBoxItem } from '../internal/reorderable-list-box/ReorderableListBox.js';
3
2
  import Icon from '../../utilities/Icon.js';
4
3
  import classNames from 'classnames';
@@ -10,32 +9,24 @@ import { ManageSavedViewsButton } from './ManageSavedViewsButton.js';
10
9
  import { ManageSavedViewsModal } from './ManageSavedViewsModal.js';
11
10
  import { NewSavedViewButton } from './NewSavedViewButton.js';
12
11
  import { NewSavedViewModal } from './NewSavedViewModal.js';
13
- import { initialView, findActiveSavedView, sortKeyAfter } from './savedViews.js';
14
- import { useActiveSavedView } from './useActiveSavedView.js';
15
- import { useUpdateSavedViewName } from './useUpdateSavedViewName.js';
12
+ import { hasSavedViewMenuActions, SavedViewMenu } from './SavedViewMenu.js';
13
+ import { isSavedViewEditable } from './savedViews.js';
14
+ import { useSavedViewNameModal } from './useSavedViewNameModal.js';
15
+ import { SaveStatusIcon, NEW_VIEW } from './useSaveStatus.js';
16
16
 
17
17
  /**
18
18
  * The id of the view the delete alert returns focus to. Read through context
19
19
  * so the list's cached items see it without rebuilding the collection.
20
20
  */
21
21
  const ReturningFocusViewIdContext = createContext(null);
22
- function SavedViewsBar({ defaultViewId, onApply, onCreate, onDelete, onSetDefault, onUpdate, savedViews, staticViews, activeFilters, hideableColumns, isColumnVisible, sortBy, }) {
22
+ function SavedViewsBar({ activeSavedView, currentState, defaultViewId, isReordering, onApply, onCreate, onDelete, onReorder, onSetDefault, onUpdate, saveStatus, savedViews, select, selectWhenSaved, staticViews, }) {
23
23
  const closeOpenContextMenuRef = useRef(null);
24
- const hasInitialView = staticViews.some(({ id }) => id === initialView.id);
25
- const staticViewsWithInitial = hasInitialView
26
- ? staticViews
27
- : [initialView, ...staticViews];
28
- const views = [...staticViewsWithInitial, ...savedViews];
24
+ const views = [...staticViews, ...savedViews];
29
25
  // The list needs a key for every view, including ones not yet saved.
30
26
  const items = views.map((view, index) => ({
31
27
  id: view.id ?? `unsaved-view-${index}`,
32
28
  view,
33
29
  }));
34
- // What the name modal saves, under the name entered there: a new view, a
35
- // duplicate, or a rename. It outlives the modal's open state so the title
36
- // holds while the modal fades out.
37
- const [draft, setDraft] = useState();
38
- const [isDraftOpen, setIsDraftOpen] = useState(false);
39
30
  const [isManageOpen, setIsManageOpen] = useState(false);
40
31
  const barRef = useRef(null);
41
32
  // Kept after the alert closes, so its text holds during the exit animation,
@@ -43,52 +34,22 @@ function SavedViewsBar({ defaultViewId, onApply, onCreate, onDelete, onSetDefaul
43
34
  const [viewToDelete, setViewToDelete] = useState(null);
44
35
  const [isDeleteAlertOpen, setIsDeleteAlertOpen] = useState(false);
45
36
  const [isReturningFocus, setIsReturningFocus] = useState(false);
46
- const hiddenColumnNames = hideableColumns
47
- .filter((column) => !isColumnVisible(column))
48
- .map(({ name }) => name);
49
- // Static views come first, so they win ties with saved views.
50
- const { activeSavedView, select, selectWhenSaved } = useActiveSavedView(views, () => findActiveSavedView(views, {
51
- activeFilters,
52
- hiddenColumnNames,
53
- sort: sortBy,
54
- }));
55
- const updateSavedViewName = useUpdateSavedViewName(onUpdate);
56
- const openDraft = (title, defaultName, save) => {
57
- setDraft({ defaultName, save, title });
58
- setIsDraftOpen(true);
59
- };
37
+ const nameModal = useSavedViewNameModal(onUpdate);
38
+ // Not in the list until it saves, so its status shows by the new view
39
+ // button.
60
40
  const createSavedView = (view) => {
61
- const sortKey = sortKeyAfter(savedViews);
62
- if (onCreate) {
63
- selectWhenSaved(onCreate({ ...view, ...(sortKey && { sortKey }) }));
64
- }
65
- };
66
- const openNewSavedView = () => {
67
- openDraft("New view", "", (name) => createSavedView({
68
- activeFilters,
69
- name,
70
- ...(hideableColumns.length > 0 && { hiddenColumnNames }),
71
- ...(sortBy && { sort: sortBy }),
72
- }));
73
- };
74
- // The copy is a new view, so it doesn't keep the original's id or place in
75
- // the order.
76
- const duplicateSavedView = ({ id: _id, sortKey: _sortKey, ...view }) => {
77
- openDraft("Duplicate view", `${view.name} copy`, (name) => createSavedView({ ...view, name }));
41
+ if (onCreate)
42
+ saveStatus.track(NEW_VIEW, selectWhenSaved(onCreate(view)), view.name);
78
43
  };
79
- const renameSavedView = (view) => {
80
- openDraft("Rename view", view.name, (name) => {
81
- if (name !== view.name)
82
- updateSavedViewName(view, name);
83
- });
44
+ // A duplicate of another view has other settings than the table, so it's
45
+ // applied once it's selected.
46
+ const duplicateSavedView = (view) => {
47
+ if (onCreate)
48
+ saveStatus.track(NEW_VIEW, selectWhenSaved(onCreate(view)).then((selected) => selected && onApply(selected)), view.name);
84
49
  };
85
- const saveDraft = (name) => {
86
- setIsDraftOpen(false);
87
- draft?.save(name);
50
+ const openNewSavedView = () => {
51
+ nameModal.open("New view", "", (name) => createSavedView({ ...currentState, name }));
88
52
  };
89
- // Updates and deletes are matched by id, so an unsaved view can't be
90
- // renamed or deleted. Static views can't be edited at all.
91
- const isEditable = (view) => view.id !== undefined && savedViews.includes(view);
92
53
  // The menu item Delete was chosen from is gone by now, so the view takes
93
54
  // focus first for the alert to return it to on cancel.
94
55
  const requestDelete = (view) => {
@@ -99,14 +60,11 @@ function SavedViewsBar({ defaultViewId, onApply, onCreate, onDelete, onSetDefaul
99
60
  setIsDeleteAlertOpen(true);
100
61
  setIsReturningFocus(true);
101
62
  };
102
- // Lets the tab stop go back to the selected view, where focus lands.
103
- // Deleting the default view hands the default back to "initial".
63
+ // Lets the tab stop go back to the selected view, where focus lands. A
64
+ // failed delete puts the view back, showing its status.
104
65
  const confirmDelete = () => {
105
- if (viewToDelete) {
106
- onDelete?.(viewToDelete);
107
- if (viewToDelete.id === defaultViewId)
108
- onSetDefault?.("initial");
109
- }
66
+ if (viewToDelete && onDelete)
67
+ saveStatus.track(viewToDelete.id, onDelete(viewToDelete), viewToDelete.name);
110
68
  setIsDeleteAlertOpen(false);
111
69
  setIsReturningFocus(false);
112
70
  };
@@ -123,25 +81,25 @@ function SavedViewsBar({ defaultViewId, onApply, onCreate, onDelete, onSetDefaul
123
81
  setIsReturningFocus(false);
124
82
  };
125
83
  const renderContextMenu = (view) => {
126
- const canRename = onUpdate && isEditable(view);
127
- const canDelete = onDelete && isEditable(view);
128
84
  // The default is matched by id, so an unsaved view can't be made the
129
85
  // default. Static views can.
130
86
  const { id } = view;
131
- const canSetDefault = onSetDefault && id !== undefined;
132
- const isDefault = id === defaultViewId;
133
- const hasActions = canRename || onCreate || canSetDefault;
134
- if (!hasActions && !canDelete)
135
- return null;
136
- return (React__default.createElement(DropdownMenu, null,
137
- canRename && (React__default.createElement(DropdownAction, { id: "rename", onAction: () => renameSavedView(view) }, "Rename")),
138
- onCreate && (React__default.createElement(DropdownAction, { id: "duplicate", onAction: () => duplicateSavedView(view) }, "Duplicate")),
139
- canSetDefault && (
140
- // Stays in the menu for the default view, disabled, so the user can
141
- // see which view is the default.
142
- React__default.createElement(DropdownAction, { disabled: isDefault, id: "set-default", onAction: () => onSetDefault(id) }, isDefault ? "Default view" : "Set as default")),
143
- hasActions && canDelete && React__default.createElement(DropdownSeparator, null),
144
- canDelete && (React__default.createElement(DropdownAction, { destructive: true, id: "delete", onAction: () => queueMicrotask(() => requestDelete(view)) }, "Delete"))));
87
+ const menuProps = {
88
+ isDefault: id === defaultViewId,
89
+ onDelete: onDelete && isSavedViewEditable(view, savedViews)
90
+ ? () => queueMicrotask(() => requestDelete(view))
91
+ : undefined,
92
+ onDuplicate: onCreate
93
+ ? () => nameModal.openDuplicate(view, duplicateSavedView)
94
+ : undefined,
95
+ onRename: onUpdate && isSavedViewEditable(view, savedViews)
96
+ ? () => nameModal.openRename(view, (saving) => saveStatus.track(view.id, saving, view.name))
97
+ : undefined,
98
+ onSetDefault: onSetDefault && id !== undefined
99
+ ? () => saveStatus.track(id, onSetDefault(id), view.name)
100
+ : undefined,
101
+ };
102
+ return hasSavedViewMenuActions(menuProps) ? (React__default.createElement(SavedViewMenu, { ...menuProps })) : null;
145
103
  };
146
104
  return (React__default.createElement("div", { ref: barRef, className: "tds-data-table-saved-views", onFocus: isReturningFocus ? handleFocus : undefined },
147
105
  React__default.createElement("div", { className: "tds-data-table-saved-views-list" },
@@ -165,15 +123,17 @@ function SavedViewsBar({ defaultViewId, onApply, onCreate, onDelete, onSetDefaul
165
123
  ...props,
166
124
  children: (React__default.createElement(React__default.Fragment, null,
167
125
  view.name,
168
- pin)),
126
+ pin,
127
+ React__default.createElement(SaveStatusIcon, { status: saveStatus.statusFor(view.id) }))),
169
128
  };
170
129
  return menu ? (React__default.createElement(ContextMenuTrigger, { id: view.id, closeOpenContextMenuRef: closeOpenContextMenuRef, menu: menu, optionProps: optionProps })) : (React__default.createElement("div", { ...optionProps }));
171
130
  } }, view.name));
172
131
  })),
173
132
  onCreate && React__default.createElement(NewSavedViewButton, { onClick: openNewSavedView }),
174
- React__default.createElement(NewSavedViewModal, { defaultName: draft?.defaultName, open: isDraftOpen, title: draft?.title, onClose: () => setIsDraftOpen(false), onSave: saveDraft })),
133
+ React__default.createElement(SaveStatusIcon, { label: "View not saved", status: saveStatus.statusFor(NEW_VIEW) }),
134
+ React__default.createElement(NewSavedViewModal, { ...nameModal.modalProps })),
175
135
  views.length > 1 && (React__default.createElement(ManageSavedViewsButton, { onClick: () => setIsManageOpen(true) })),
176
- React__default.createElement(ManageSavedViewsModal, { defaultViewId: defaultViewId, open: isManageOpen, savedViews: savedViews, staticViews: staticViewsWithInitial, onClose: closeManageViews, onDelete: onDelete, onSetDefault: onSetDefault, onUpdate: onUpdate }),
136
+ React__default.createElement(ManageSavedViewsModal, { defaultViewId: defaultViewId, isReordering: isReordering, open: isManageOpen, savedViews: savedViews, staticViews: staticViews, onClose: closeManageViews, onCreate: onCreate, onDelete: onDelete, onReorder: onReorder, onSetDefault: onSetDefault, onUpdate: onUpdate }),
177
137
  onDelete && (React__default.createElement(DeleteSavedViewAlertDialog, { open: isDeleteAlertOpen, view: viewToDelete, onCancel: () => setIsDeleteAlertOpen(false), onConfirm: confirmDelete }))));
178
138
  }
179
139
  SavedViewsBar.displayName = "SavedViewsBar";
@@ -1 +1 @@
1
- {"version":3,"file":"SavedViewsBar.js","sources":["../../../src/components/DataTable/SavedViewsBar.tsx"],"sourcesContent":["import {\n DropdownAction,\n DropdownMenu,\n DropdownSeparator,\n} from \"@components/dropdown\"\nimport {\n ReorderableListBox,\n ReorderableListBoxItem,\n} from \"@components/internal/reorderable-list-box\"\nimport Icon from \"@utilities/Icon\"\nimport classNames from \"classnames\"\nimport React, {\n type ComponentProps,\n createContext,\n Fragment,\n type KeyboardEvent,\n type MutableRefObject,\n type ReactElement,\n type RefObject,\n useCallback,\n useContext,\n useEffect,\n useRef,\n useState,\n} from \"react\"\nimport { mergeProps } from \"react-aria/mergeProps\"\nimport { MenuTrigger, Pressable } from \"react-aria-components/Menu\"\n\nimport type { Sort } from \"./DataTable\"\nimport type { DataTableColumn } from \"./DataTableColumn\"\nimport { DeleteSavedViewAlertDialog } from \"./DeleteSavedViewAlertDialog\"\nimport type { ActiveFilter } from \"./FilterTypes\"\nimport { ManageSavedViewsButton } from \"./ManageSavedViewsButton\"\nimport { ManageSavedViewsModal } from \"./ManageSavedViewsModal\"\nimport { NewSavedViewButton } from \"./NewSavedViewButton\"\nimport { NewSavedViewModal } from \"./NewSavedViewModal\"\nimport {\n findActiveSavedView,\n initialView,\n type SavedView,\n sortKeyAfter,\n type StaticView,\n} from \"./savedViews\"\nimport { useActiveSavedView } from \"./useActiveSavedView\"\nimport { useUpdateSavedViewName } from \"./useUpdateSavedViewName\"\n\n/**\n * The id of the view the delete alert returns focus to. Read through context\n * so the list's cached items see it without rebuilding the collection.\n */\nconst ReturningFocusViewIdContext = createContext<SavedView[\"id\"] | null>(null)\n\nexport interface SavedViewsBarProps {\n activeFilters: ActiveFilter[]\n defaultViewId: NonNullable<SavedView[\"id\"]>\n hideableColumns: DataTableColumn[]\n isColumnVisible: (column: DataTableColumn) => boolean\n onApply: (savedView: SavedView) => void\n /**\n * Returns the saved view with its new id. Omit to hide the new view button\n * and the Duplicate action.\n */\n onCreate?: (\n savedView: Omit<SavedView, \"id\">\n ) => Promise<SavedView> | SavedView\n /** Called once the user confirms. Omit to leave out the Delete action. */\n onDelete?: (savedView: SavedView) => void\n /** Omit to leave out the Set as default action. */\n onSetDefault?: (id: NonNullable<SavedView[\"id\"]>) => void\n /** Omit to leave out the Rename action. */\n onUpdate?: (savedView: SavedView) => Promise<SavedView> | SavedView\n savedViews: SavedView[]\n sortBy: Sort | undefined\n /** Listed before `savedViews` and can't be edited. */\n staticViews: StaticView[]\n}\n\nexport function SavedViewsBar({\n defaultViewId,\n onApply,\n onCreate,\n onDelete,\n onSetDefault,\n onUpdate,\n savedViews,\n staticViews,\n activeFilters,\n hideableColumns,\n isColumnVisible,\n sortBy,\n}: SavedViewsBarProps) {\n const closeOpenContextMenuRef = useRef<(() => void) | null>(null)\n const hasInitialView = staticViews.some(({ id }) => id === initialView.id)\n const staticViewsWithInitial = hasInitialView\n ? staticViews\n : [initialView, ...staticViews]\n const views = [...staticViewsWithInitial, ...savedViews]\n // The list needs a key for every view, including ones not yet saved.\n const items = views.map((view, index) => ({\n id: view.id ?? `unsaved-view-${index}`,\n view,\n }))\n // What the name modal saves, under the name entered there: a new view, a\n // duplicate, or a rename. It outlives the modal's open state so the title\n // holds while the modal fades out.\n const [draft, setDraft] = useState<{\n defaultName: string\n save: (name: string) => void\n title: string\n }>()\n const [isDraftOpen, setIsDraftOpen] = useState(false)\n const [isManageOpen, setIsManageOpen] = useState(false)\n const barRef = useRef<HTMLDivElement>(null)\n // Kept after the alert closes, so its text holds during the exit animation,\n // and its view keeps the tab stop until focus returns to it on cancel.\n const [viewToDelete, setViewToDelete] = useState<SavedView | null>(null)\n const [isDeleteAlertOpen, setIsDeleteAlertOpen] = useState(false)\n const [isReturningFocus, setIsReturningFocus] = useState(false)\n const hiddenColumnNames = hideableColumns\n .filter((column) => !isColumnVisible(column))\n .map(({ name }) => name)\n // Static views come first, so they win ties with saved views.\n const { activeSavedView, select, selectWhenSaved } = useActiveSavedView(\n views,\n () =>\n findActiveSavedView(views, {\n activeFilters,\n hiddenColumnNames,\n sort: sortBy,\n })\n )\n\n const updateSavedViewName = useUpdateSavedViewName(onUpdate)\n\n const openDraft = (\n title: string,\n defaultName: string,\n save: (name: string) => void\n ) => {\n setDraft({ defaultName, save, title })\n setIsDraftOpen(true)\n }\n\n const createSavedView = (view: Omit<SavedView, \"id\">) => {\n const sortKey = sortKeyAfter(savedViews)\n if (onCreate) {\n selectWhenSaved(onCreate({ ...view, ...(sortKey && { sortKey }) }))\n }\n }\n\n const openNewSavedView = () => {\n openDraft(\"New view\", \"\", (name) =>\n createSavedView({\n activeFilters,\n name,\n ...(hideableColumns.length > 0 && { hiddenColumnNames }),\n ...(sortBy && { sort: sortBy }),\n })\n )\n }\n\n // The copy is a new view, so it doesn't keep the original's id or place in\n // the order.\n const duplicateSavedView = ({\n id: _id,\n sortKey: _sortKey,\n ...view\n }: SavedView) => {\n openDraft(\"Duplicate view\", `${view.name} copy`, (name) =>\n createSavedView({ ...view, name })\n )\n }\n\n const renameSavedView = (view: SavedView) => {\n openDraft(\"Rename view\", view.name, (name) => {\n if (name !== view.name) updateSavedViewName(view, name)\n })\n }\n\n const saveDraft = (name: string) => {\n setIsDraftOpen(false)\n draft?.save(name)\n }\n\n // Updates and deletes are matched by id, so an unsaved view can't be\n // renamed or deleted. Static views can't be edited at all.\n const isEditable = (view: SavedView) =>\n view.id !== undefined && savedViews.includes(view)\n\n // The menu item Delete was chosen from is gone by now, so the view takes\n // focus first for the alert to return it to on cancel.\n const requestDelete = (view: SavedView) => {\n barRef.current\n ?.querySelector<HTMLElement>(\n `[role=\"option\"][data-key=\"${CSS.escape(String(view.id))}\"]`\n )\n ?.focus()\n setViewToDelete(view)\n setIsDeleteAlertOpen(true)\n setIsReturningFocus(true)\n }\n\n // Lets the tab stop go back to the selected view, where focus lands.\n // Deleting the default view hands the default back to \"initial\".\n const confirmDelete = () => {\n if (viewToDelete) {\n onDelete?.(viewToDelete)\n if (viewToDelete.id === defaultViewId) onSetDefault?.(\"initial\")\n }\n setIsDeleteAlertOpen(false)\n setIsReturningFocus(false)\n }\n\n const focusSelectedViewAfterClose = useFocusSelectedViewAfterClose(\n barRef,\n isManageOpen\n )\n\n // Deleting down to one view hides the button the modal returns focus to.\n const closeManageViews = () => {\n if (views.length <= 1) focusSelectedViewAfterClose()\n setIsManageOpen(false)\n }\n\n // Focus from inside the open alert reaches here too, through the portal.\n const handleFocus = () => {\n if (!isDeleteAlertOpen) setIsReturningFocus(false)\n }\n\n const renderContextMenu = (view: SavedView) => {\n const canRename = onUpdate && isEditable(view)\n const canDelete = onDelete && isEditable(view)\n // The default is matched by id, so an unsaved view can't be made the\n // default. Static views can.\n const { id } = view\n const canSetDefault = onSetDefault && id !== undefined\n const isDefault = id === defaultViewId\n const hasActions = canRename || onCreate || canSetDefault\n if (!hasActions && !canDelete) return null\n return (\n <DropdownMenu>\n {canRename && (\n <DropdownAction id=\"rename\" onAction={() => renameSavedView(view)}>\n Rename\n </DropdownAction>\n )}\n {onCreate && (\n <DropdownAction\n id=\"duplicate\"\n onAction={() => duplicateSavedView(view)}\n >\n Duplicate\n </DropdownAction>\n )}\n {canSetDefault && (\n // Stays in the menu for the default view, disabled, so the user can\n // see which view is the default.\n <DropdownAction\n disabled={isDefault}\n id=\"set-default\"\n onAction={() => onSetDefault(id)}\n >\n {isDefault ? \"Default view\" : \"Set as default\"}\n </DropdownAction>\n )}\n {hasActions && canDelete && <DropdownSeparator />}\n {canDelete && (\n <DropdownAction\n destructive\n id=\"delete\"\n onAction={() => queueMicrotask(() => requestDelete(view))}\n >\n Delete\n </DropdownAction>\n )}\n </DropdownMenu>\n )\n }\n\n return (\n <div\n ref={barRef}\n className=\"tds-data-table-saved-views\"\n onFocus={isReturningFocus ? handleFocus : undefined}\n >\n <div className=\"tds-data-table-saved-views-list\">\n <ReturningFocusViewIdContext.Provider\n value={isReturningFocus ? (viewToDelete?.id ?? null) : null}\n >\n <ReorderableListBox\n items={items}\n label=\"Views\"\n selectedKey={activeSavedView?.id ?? null}\n onSelectionChange={(key) => {\n const view = items.find(({ id }) => id === key)?.view\n if (!view) return\n select(view)\n onApply(view)\n }}\n >\n {({ id, view }) => {\n const menu = renderContextMenu(view)\n // The first view is the default unless another is marked.\n const pin = view.id === defaultViewId && id !== items[0].id && (\n <Icon\n aria-hidden\n className=\"tds-data-table-saved-view-default-indicator\"\n symbol=\"general#pin\"\n />\n )\n return (\n <ReorderableListBoxItem\n className={classNames(\"tds-data-table-saved-view-list-item\", {\n \"tds-data-table-saved-view-list-item--default\":\n view.id === defaultViewId,\n })}\n id={id}\n // The list item only takes text, so the pin goes in here.\n render={(props) => {\n const optionProps = {\n ...(props as ComponentProps<\"div\">),\n children: (\n <>\n {view.name}\n {pin}\n </>\n ),\n }\n return menu ? (\n <ContextMenuTrigger\n id={view.id}\n closeOpenContextMenuRef={closeOpenContextMenuRef}\n menu={menu}\n optionProps={optionProps}\n />\n ) : (\n <div {...optionProps} />\n )\n }}\n >\n {view.name}\n </ReorderableListBoxItem>\n )\n }}\n </ReorderableListBox>\n </ReturningFocusViewIdContext.Provider>\n {onCreate && <NewSavedViewButton onClick={openNewSavedView} />}\n <NewSavedViewModal\n defaultName={draft?.defaultName}\n open={isDraftOpen}\n title={draft?.title}\n onClose={() => setIsDraftOpen(false)}\n onSave={saveDraft}\n />\n </div>\n {views.length > 1 && (\n <ManageSavedViewsButton onClick={() => setIsManageOpen(true)} />\n )}\n {/* Rendered apart from the button, so a delete that hides the button doesn't remove the open modal. */}\n <ManageSavedViewsModal\n defaultViewId={defaultViewId}\n open={isManageOpen}\n savedViews={savedViews}\n staticViews={staticViewsWithInitial}\n onClose={closeManageViews}\n onDelete={onDelete}\n onSetDefault={onSetDefault}\n onUpdate={onUpdate}\n />\n {onDelete && (\n <DeleteSavedViewAlertDialog\n open={isDeleteAlertOpen}\n view={viewToDelete}\n onCancel={() => setIsDeleteAlertOpen(false)}\n onConfirm={confirmDelete}\n />\n )}\n </div>\n )\n}\n\nSavedViewsBar.displayName = \"SavedViewsBar\"\n\n/**\n * Once the manage views modal starts closing, focuses the selected view, or\n * the first one.\n */\nfunction useFocusSelectedViewAfterClose(\n barRef: RefObject<HTMLDivElement>,\n isManageOpen: boolean\n) {\n const shouldFocusRef = useRef(false)\n\n useEffect(() => {\n if (isManageOpen || !shouldFocusRef.current) return\n shouldFocusRef.current = false\n const bar = barRef.current\n ;(\n bar?.querySelector<HTMLElement>(\n '[role=\"option\"][aria-selected=\"true\"]'\n ) ?? bar?.querySelector<HTMLElement>('[role=\"option\"]')\n )?.focus()\n }, [barRef, isManageOpen])\n\n return () => {\n shouldFocusRef.current = true\n }\n}\n\n/**\n * Makes a saved view's option element itself the context menu trigger, so\n * the menu opens by right click, long press, or the keyboard context menu\n * shortcut (Shift+F10, the Menu key, or Ctrl+Enter on macOS), is named by\n * the view, and returns focus to it on close. `Pressable` hands the trigger's\n * handlers to the option element. The option ignores Ctrl+Enter, so the\n * macOS shortcut opens the menu without also selecting the view. The\n * `data-popup-open` attribute keeps the list from moving its tab\n * stop to the selected view while the menu is open. Opening the menu closes\n * any other view's menu, since a right click elsewhere in the list doesn't\n * count as an outside interaction. The open state stays here rather than in\n * the bar, because re-rendering the bar rebuilds the list's collection and\n * moves its tab stop before focus can return to this view. Each\n * `contextmenu` event remounts the menu, because React Aria only positions\n * an open menu once and would leave it at the first click point.\n */\nfunction ContextMenuTrigger({\n closeOpenContextMenuRef,\n id,\n menu,\n optionProps,\n}: {\n closeOpenContextMenuRef: MutableRefObject<(() => void) | null>\n id: SavedView[\"id\"]\n menu: ReactElement\n optionProps: ComponentProps<\"div\">\n}) {\n const { onKeyDown, ...restOptionProps } = optionProps\n const [isOpen, setIsOpen] = useState(false)\n // Such as the delete alert, which returns focus to this view on cancel.\n const hasOtherPopup = useContext(ReturningFocusViewIdContext) === id\n const [menuKey, setMenuKey] = useState(0)\n\n const close = useCallback(() => setIsOpen(false), [])\n const handleOpenChange = (nextIsOpen: boolean) => {\n setIsOpen(nextIsOpen)\n if (nextIsOpen) {\n closeOpenContextMenuRef.current?.()\n closeOpenContextMenuRef.current = close\n } else if (closeOpenContextMenuRef.current === close) {\n closeOpenContextMenuRef.current = null\n }\n }\n\n return (\n <MenuTrigger\n isOpen={isOpen}\n onOpenChange={handleOpenChange}\n trigger=\"contextMenu\"\n >\n <Pressable>\n <div\n {...mergeProps(restOptionProps, {\n \"data-popup-open\": isOpen || hasOtherPopup || undefined,\n onContextMenu: () => setMenuKey((key) => key + 1),\n onKeyDown: (event: KeyboardEvent<HTMLDivElement>) => {\n if (event.ctrlKey && event.key === \"Enter\") return\n onKeyDown?.(event)\n },\n })}\n />\n </Pressable>\n <Fragment key={menuKey}>{menu}</Fragment>\n </MenuTrigger>\n )\n}\n"],"names":["React"],"mappings":"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"}
1
+ {"version":3,"file":"SavedViewsBar.js","sources":["../../../src/components/DataTable/SavedViewsBar.tsx"],"sourcesContent":["import {\n ReorderableListBox,\n ReorderableListBoxItem,\n} from \"@components/internal/reorderable-list-box\"\nimport Icon from \"@utilities/Icon\"\nimport classNames from \"classnames\"\nimport React, {\n type ComponentProps,\n createContext,\n Fragment,\n type KeyboardEvent,\n type MutableRefObject,\n type ReactElement,\n type RefObject,\n useCallback,\n useContext,\n useEffect,\n useRef,\n useState,\n} from \"react\"\nimport { mergeProps } from \"react-aria/mergeProps\"\nimport { MenuTrigger, Pressable } from \"react-aria-components/Menu\"\n\nimport { DeleteSavedViewAlertDialog } from \"./DeleteSavedViewAlertDialog\"\nimport { ManageSavedViewsButton } from \"./ManageSavedViewsButton\"\nimport { ManageSavedViewsModal } from \"./ManageSavedViewsModal\"\nimport { NewSavedViewButton } from \"./NewSavedViewButton\"\nimport { NewSavedViewModal } from \"./NewSavedViewModal\"\nimport { hasSavedViewMenuActions, SavedViewMenu } from \"./SavedViewMenu\"\nimport {\n isSavedViewEditable,\n type SavedView,\n type StaticView,\n} from \"./savedViews\"\nimport { useSavedViewNameModal } from \"./useSavedViewNameModal\"\nimport type { ReorderTarget } from \"./useSavedViewsState\"\nimport { NEW_VIEW, SaveStatusIcon, type useSaveStatus } from \"./useSaveStatus\"\n\n/**\n * The id of the view the delete alert returns focus to. Read through context\n * so the list's cached items see it without rebuilding the collection.\n */\nconst ReturningFocusViewIdContext = createContext<SavedView[\"id\"] | null>(null)\n\nexport interface SavedViewsBarProps {\n /** The selected view, if any. */\n activeSavedView: SavedView | undefined\n /** What New view saves. Its filters leave out the search. */\n currentState: Omit<SavedView, \"id\" | \"name\">\n defaultViewId: NonNullable<SavedView[\"id\"]>\n /** Disables the drag handles while a reorder saves. */\n isReordering?: boolean\n onApply: (savedView: SavedView) => void\n /**\n * Returns the saved view with its new id. Omit to hide the new view button\n * and the Duplicate action.\n */\n onCreate?: (\n savedView: Omit<SavedView, \"id\">\n ) => Promise<SavedView | undefined> | SavedView\n /** Called once the user confirms. Omit to leave out the Delete action. */\n onDelete?: (savedView: SavedView) => Promise<void>\n /** Omit to leave out the drag handles in the manage views modal. */\n onReorder?: (savedView: SavedView, target: ReorderTarget) => Promise<void>\n /** Omit to leave out the Set as default action. */\n onSetDefault?: (id: NonNullable<SavedView[\"id\"]>) => Promise<void>\n /** Omit to leave out the Rename action. */\n onUpdate?: (\n savedView: SavedView\n ) => Promise<SavedView | undefined> | SavedView\n /** Tracks saves, shared with the filters shelf's saved view actions. */\n saveStatus: ReturnType<typeof useSaveStatus>\n savedViews: SavedView[]\n /** Selects the view the user picked. */\n select: (savedView: SavedView) => void\n /** Selects a created view once it's saved, resolving to it if selected. */\n selectWhenSaved: (\n savedView: Promise<SavedView | undefined> | SavedView\n ) => Promise<SavedView | undefined>\n /**\n * Listed before `savedViews` and can't be edited. Starts with the initial\n * view unless one replaces it.\n */\n staticViews: StaticView[]\n}\n\nexport function SavedViewsBar({\n activeSavedView,\n currentState,\n defaultViewId,\n isReordering,\n onApply,\n onCreate,\n onDelete,\n onReorder,\n onSetDefault,\n onUpdate,\n saveStatus,\n savedViews,\n select,\n selectWhenSaved,\n staticViews,\n}: SavedViewsBarProps) {\n const closeOpenContextMenuRef = useRef<(() => void) | null>(null)\n const views = [...staticViews, ...savedViews]\n // The list needs a key for every view, including ones not yet saved.\n const items = views.map((view, index) => ({\n id: view.id ?? `unsaved-view-${index}`,\n view,\n }))\n const [isManageOpen, setIsManageOpen] = useState(false)\n const barRef = useRef<HTMLDivElement>(null)\n // Kept after the alert closes, so its text holds during the exit animation,\n // and its view keeps the tab stop until focus returns to it on cancel.\n const [viewToDelete, setViewToDelete] = useState<SavedView | null>(null)\n const [isDeleteAlertOpen, setIsDeleteAlertOpen] = useState(false)\n const [isReturningFocus, setIsReturningFocus] = useState(false)\n\n const nameModal = useSavedViewNameModal(onUpdate)\n\n // Not in the list until it saves, so its status shows by the new view\n // button.\n const createSavedView = (view: Omit<SavedView, \"id\">) => {\n if (onCreate)\n saveStatus.track(NEW_VIEW, selectWhenSaved(onCreate(view)), view.name)\n }\n\n // A duplicate of another view has other settings than the table, so it's\n // applied once it's selected.\n const duplicateSavedView = (view: Omit<SavedView, \"id\">) => {\n if (onCreate)\n saveStatus.track(\n NEW_VIEW,\n selectWhenSaved(onCreate(view)).then(\n (selected) => selected && onApply(selected)\n ),\n view.name\n )\n }\n\n const openNewSavedView = () => {\n nameModal.open(\"New view\", \"\", (name) =>\n createSavedView({ ...currentState, name })\n )\n }\n\n // The menu item Delete was chosen from is gone by now, so the view takes\n // focus first for the alert to return it to on cancel.\n const requestDelete = (view: SavedView) => {\n barRef.current\n ?.querySelector<HTMLElement>(\n `[role=\"option\"][data-key=\"${CSS.escape(String(view.id))}\"]`\n )\n ?.focus()\n setViewToDelete(view)\n setIsDeleteAlertOpen(true)\n setIsReturningFocus(true)\n }\n\n // Lets the tab stop go back to the selected view, where focus lands. A\n // failed delete puts the view back, showing its status.\n const confirmDelete = () => {\n if (viewToDelete && onDelete)\n saveStatus.track(\n viewToDelete.id,\n onDelete(viewToDelete),\n viewToDelete.name\n )\n setIsDeleteAlertOpen(false)\n setIsReturningFocus(false)\n }\n\n const focusSelectedViewAfterClose = useFocusSelectedViewAfterClose(\n barRef,\n isManageOpen\n )\n\n // Deleting down to one view hides the button the modal returns focus to.\n const closeManageViews = () => {\n if (views.length <= 1) focusSelectedViewAfterClose()\n setIsManageOpen(false)\n }\n\n // Focus from inside the open alert reaches here too, through the portal.\n const handleFocus = () => {\n if (!isDeleteAlertOpen) setIsReturningFocus(false)\n }\n\n const renderContextMenu = (view: SavedView) => {\n // The default is matched by id, so an unsaved view can't be made the\n // default. Static views can.\n const { id } = view\n const menuProps = {\n isDefault: id === defaultViewId,\n onDelete:\n onDelete && isSavedViewEditable(view, savedViews)\n ? () => queueMicrotask(() => requestDelete(view))\n : undefined,\n onDuplicate: onCreate\n ? () => nameModal.openDuplicate(view, duplicateSavedView)\n : undefined,\n onRename:\n onUpdate && isSavedViewEditable(view, savedViews)\n ? () =>\n nameModal.openRename(view, (saving) =>\n saveStatus.track(view.id, saving, view.name)\n )\n : undefined,\n onSetDefault:\n onSetDefault && id !== undefined\n ? () => saveStatus.track(id, onSetDefault(id), view.name)\n : undefined,\n }\n return hasSavedViewMenuActions(menuProps) ? (\n <SavedViewMenu {...menuProps} />\n ) : null\n }\n\n return (\n <div\n ref={barRef}\n className=\"tds-data-table-saved-views\"\n onFocus={isReturningFocus ? handleFocus : undefined}\n >\n <div className=\"tds-data-table-saved-views-list\">\n <ReturningFocusViewIdContext.Provider\n value={isReturningFocus ? (viewToDelete?.id ?? null) : null}\n >\n <ReorderableListBox\n items={items}\n label=\"Views\"\n selectedKey={activeSavedView?.id ?? null}\n onSelectionChange={(key) => {\n const view = items.find(({ id }) => id === key)?.view\n if (!view) return\n select(view)\n onApply(view)\n }}\n >\n {({ id, view }) => {\n const menu = renderContextMenu(view)\n // The first view is the default unless another is marked.\n const pin = view.id === defaultViewId && id !== items[0].id && (\n <Icon\n aria-hidden\n className=\"tds-data-table-saved-view-default-indicator\"\n symbol=\"general#pin\"\n />\n )\n return (\n <ReorderableListBoxItem\n className={classNames(\"tds-data-table-saved-view-list-item\", {\n \"tds-data-table-saved-view-list-item--default\":\n view.id === defaultViewId,\n })}\n id={id}\n // The list item only takes text, so the pin goes in here.\n render={(props) => {\n const optionProps = {\n ...(props as ComponentProps<\"div\">),\n children: (\n <>\n {view.name}\n {pin}\n <SaveStatusIcon\n status={saveStatus.statusFor(view.id)}\n />\n </>\n ),\n }\n return menu ? (\n <ContextMenuTrigger\n id={view.id}\n closeOpenContextMenuRef={closeOpenContextMenuRef}\n menu={menu}\n optionProps={optionProps}\n />\n ) : (\n <div {...optionProps} />\n )\n }}\n >\n {view.name}\n </ReorderableListBoxItem>\n )\n }}\n </ReorderableListBox>\n </ReturningFocusViewIdContext.Provider>\n {onCreate && <NewSavedViewButton onClick={openNewSavedView} />}\n <SaveStatusIcon\n label=\"View not saved\"\n status={saveStatus.statusFor(NEW_VIEW)}\n />\n <NewSavedViewModal {...nameModal.modalProps} />\n </div>\n {views.length > 1 && (\n <ManageSavedViewsButton onClick={() => setIsManageOpen(true)} />\n )}\n {/* Rendered apart from the button, so a delete that hides the button doesn't remove the open modal. */}\n <ManageSavedViewsModal\n defaultViewId={defaultViewId}\n isReordering={isReordering}\n open={isManageOpen}\n savedViews={savedViews}\n staticViews={staticViews}\n onClose={closeManageViews}\n onCreate={onCreate}\n onDelete={onDelete}\n onReorder={onReorder}\n onSetDefault={onSetDefault}\n onUpdate={onUpdate}\n />\n {onDelete && (\n <DeleteSavedViewAlertDialog\n open={isDeleteAlertOpen}\n view={viewToDelete}\n onCancel={() => setIsDeleteAlertOpen(false)}\n onConfirm={confirmDelete}\n />\n )}\n </div>\n )\n}\n\nSavedViewsBar.displayName = \"SavedViewsBar\"\n\n/**\n * Once the manage views modal starts closing, focuses the selected view, or\n * the first one.\n */\nfunction useFocusSelectedViewAfterClose(\n barRef: RefObject<HTMLDivElement>,\n isManageOpen: boolean\n) {\n const shouldFocusRef = useRef(false)\n\n useEffect(() => {\n if (isManageOpen || !shouldFocusRef.current) return\n shouldFocusRef.current = false\n const bar = barRef.current\n ;(\n bar?.querySelector<HTMLElement>(\n '[role=\"option\"][aria-selected=\"true\"]'\n ) ?? bar?.querySelector<HTMLElement>('[role=\"option\"]')\n )?.focus()\n }, [barRef, isManageOpen])\n\n return () => {\n shouldFocusRef.current = true\n }\n}\n\n/**\n * Makes a saved view's option element itself the context menu trigger, so\n * the menu opens by right click, long press, or the keyboard context menu\n * shortcut (Shift+F10, the Menu key, or Ctrl+Enter on macOS), is named by\n * the view, and returns focus to it on close. `Pressable` hands the trigger's\n * handlers to the option element. The option ignores Ctrl+Enter, so the\n * macOS shortcut opens the menu without also selecting the view. The\n * `data-popup-open` attribute keeps the list from moving its tab\n * stop to the selected view while the menu is open. Opening the menu closes\n * any other view's menu, since a right click elsewhere in the list doesn't\n * count as an outside interaction. The open state stays here rather than in\n * the bar, because re-rendering the bar rebuilds the list's collection and\n * moves its tab stop before focus can return to this view. Each\n * `contextmenu` event remounts the menu, because React Aria only positions\n * an open menu once and would leave it at the first click point.\n */\nfunction ContextMenuTrigger({\n closeOpenContextMenuRef,\n id,\n menu,\n optionProps,\n}: {\n closeOpenContextMenuRef: MutableRefObject<(() => void) | null>\n id: SavedView[\"id\"]\n menu: ReactElement\n optionProps: ComponentProps<\"div\">\n}) {\n const { onKeyDown, ...restOptionProps } = optionProps\n const [isOpen, setIsOpen] = useState(false)\n // Such as the delete alert, which returns focus to this view on cancel.\n const hasOtherPopup = useContext(ReturningFocusViewIdContext) === id\n const [menuKey, setMenuKey] = useState(0)\n\n const close = useCallback(() => setIsOpen(false), [])\n const handleOpenChange = (nextIsOpen: boolean) => {\n setIsOpen(nextIsOpen)\n if (nextIsOpen) {\n closeOpenContextMenuRef.current?.()\n closeOpenContextMenuRef.current = close\n } else if (closeOpenContextMenuRef.current === close) {\n closeOpenContextMenuRef.current = null\n }\n }\n\n return (\n <MenuTrigger\n isOpen={isOpen}\n onOpenChange={handleOpenChange}\n trigger=\"contextMenu\"\n >\n <Pressable>\n <div\n {...mergeProps(restOptionProps, {\n \"data-popup-open\": isOpen || hasOtherPopup || undefined,\n onContextMenu: () => setMenuKey((key) => key + 1),\n onKeyDown: (event: KeyboardEvent<HTMLDivElement>) => {\n if (event.ctrlKey && event.key === \"Enter\") return\n onKeyDown?.(event)\n },\n })}\n />\n </Pressable>\n <Fragment key={menuKey}>{menu}</Fragment>\n </MenuTrigger>\n )\n}\n"],"names":["React"],"mappings":"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"}
@@ -23,7 +23,7 @@ export interface TableActionsProps {
23
23
  /** The table actions to render as an `IconButton` group. */
24
24
  actions: TableAction<DataTableSelection>[];
25
25
  /**
26
- * The noun used to describe the selection in each action's `aria-label`.
26
+ * The noun used to describe the selection in the group's `aria-label`.
27
27
  * See {@link ResultNoun}.
28
28
  */
29
29
  resultNoun?: ResultNoun;
@@ -31,7 +31,9 @@ export interface TableActionsProps {
31
31
  /**
32
32
  * Renders the table actions as an `IconButton` group displayed directly after
33
33
  * the results count, above the table. Each entry becomes an icon button whose
34
- * `callback` receives the current selection.
34
+ * `callback` receives the current selection. The group's label carries the
35
+ * selected count, so screen readers announce it once on entering the group
36
+ * rather than on every button.
35
37
  */
36
38
  export declare const TableActions: {
37
39
  ({ actions, resultNoun }: TableActionsProps): React.JSX.Element;
@@ -1 +1 @@
1
- {"version":3,"file":"TableActions.d.ts","sourceRoot":"","sources":["../../../src/components/DataTable/TableActions.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,EAAE,KAAK,SAAS,EAAE,MAAM,OAAO,CAAA;AAE7C,OAAO,EAA4B,KAAK,UAAU,EAAE,MAAM,gBAAgB,CAAA;AAC1E,OAAO,EACL,KAAK,kBAAkB,EAExB,MAAM,yBAAyB,CAAA;AAEhC;;;;;GAKG;AACH,MAAM,MAAM,WAAW,CACrB,cAAc,SAAS,kBAAkB,GAAG,CAAC,MAAM,GAAG,MAAM,CAAC,EAAE,IAC7D;IACF,sEAAsE;IACtE,QAAQ,CAAC,EAAE,CAAC,SAAS,EAAE,cAAc,KAAK,IAAI,CAAA;IAC9C,+CAA+C;IAC/C,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,yDAAyD;IACzD,IAAI,EAAE,SAAS,CAAA;IACf,wDAAwD;IACxD,KAAK,EAAE,MAAM,CAAA;IACb,8EAA8E;IAC9E,OAAO,CAAC,EAAE,KAAK,CAAC,iBAAiB,CAAC,iBAAiB,CAAC,CAAA;CACrD,CAAA;AAED,MAAM,WAAW,iBAAiB;IAChC,4DAA4D;IAC5D,OAAO,EAAE,WAAW,CAAC,kBAAkB,CAAC,EAAE,CAAA;IAC1C;;;OAGG;IACH,UAAU,CAAC,EAAE,UAAU,CAAA;CACxB;AAED;;;;GAIG;AACH,eAAO,MAAM,YAAY;8BAA6B,iBAAiB;;CAwBtE,CAAA"}
1
+ {"version":3,"file":"TableActions.d.ts","sourceRoot":"","sources":["../../../src/components/DataTable/TableActions.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,EAAE,KAAK,SAAS,EAAE,MAAM,OAAO,CAAA;AAE7C,OAAO,EAA4B,KAAK,UAAU,EAAE,MAAM,gBAAgB,CAAA;AAC1E,OAAO,EACL,KAAK,kBAAkB,EAExB,MAAM,yBAAyB,CAAA;AAEhC;;;;;GAKG;AACH,MAAM,MAAM,WAAW,CACrB,cAAc,SAAS,kBAAkB,GAAG,CAAC,MAAM,GAAG,MAAM,CAAC,EAAE,IAC7D;IACF,sEAAsE;IACtE,QAAQ,CAAC,EAAE,CAAC,SAAS,EAAE,cAAc,KAAK,IAAI,CAAA;IAC9C,+CAA+C;IAC/C,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,yDAAyD;IACzD,IAAI,EAAE,SAAS,CAAA;IACf,wDAAwD;IACxD,KAAK,EAAE,MAAM,CAAA;IACb,8EAA8E;IAC9E,OAAO,CAAC,EAAE,KAAK,CAAC,iBAAiB,CAAC,iBAAiB,CAAC,CAAA;CACrD,CAAA;AAED,MAAM,WAAW,iBAAiB;IAChC,4DAA4D;IAC5D,OAAO,EAAE,WAAW,CAAC,kBAAkB,CAAC,EAAE,CAAA;IAC1C;;;OAGG;IACH,UAAU,CAAC,EAAE,UAAU,CAAA;CACxB;AAED;;;;;;GAMG;AACH,eAAO,MAAM,YAAY;8BAA6B,iBAAiB;;CAuBtE,CAAA"}
@@ -13,32 +13,29 @@ import { useDataTableSelectionContext } from './useDataTableSelection.js';
13
13
  /**
14
14
  * Renders the table actions as an `IconButton` group displayed directly after
15
15
  * the results count, above the table. Each entry becomes an icon button whose
16
- * `callback` receives the current selection.
16
+ * `callback` receives the current selection. The group's label carries the
17
+ * selected count, so screen readers announce it once on entering the group
18
+ * rather than on every button.
17
19
  */
18
20
  const TableActions = ({ actions, resultNoun }) => {
19
21
  const { selectedCount, selection } = useDataTableSelectionContext();
20
- // The count/noun suffix is the same for every table action, so compute it once
21
- // here rather than per-button inside the map below.
22
- const countSuffix = getTableActionCountSuffix(selectedCount, resultNoun);
23
- return (React__default.createElement(ButtonGroup, { "aria-label": "Table actions" }, actions.map(({ callback, disabled, icon, label, onClick }) => (React__default.createElement(IconButton, { key: label, "aria-label": `${label}${countSuffix}`, disabled: disabled, icon: icon, onClick: (event) => {
22
+ return (React__default.createElement(ButtonGroup, { "aria-label": getTableActionsGroupLabel(selectedCount, resultNoun) }, actions.map(({ callback, disabled, icon, label, onClick }) => (React__default.createElement(IconButton, { key: label, "aria-label": label, disabled: disabled, icon: icon, onClick: (event) => {
24
23
  onClick?.(event);
25
24
  callback?.(selection);
26
25
  }, tooltip: label, tooltipPlacement: "bottom" })))));
27
26
  };
28
27
  TableActions.displayName = "TableActions";
29
28
  /**
30
- * The count/noun suffix appended to each table action's `aria-label` when rows
31
- * are selected, e.g. `" (2 selected people)"` — so `"Email"` reads as
32
- * `"Email (2 selected people)"`. Empty when nothing is selected. Falls back to
33
- * the default `"result"` noun when `resultNoun` isn't provided. Shared across
34
- * every action, so it's computed once rather than per-button.
29
+ * The table actions group's `aria-label`, e.g. `"Actions for 2 selected
30
+ * people"` when rows are selected, or `"Table actions"` when nothing is
31
+ * selected. Falls back to the default `"result"` noun when `resultNoun` isn't
32
+ * provided.
35
33
  */
36
- function getTableActionCountSuffix(count, resultNoun) {
34
+ function getTableActionsGroupLabel(count, resultNoun) {
37
35
  if (!count)
38
- return "";
39
- // An absent or `true` noun both default to `"result"`/`"results"`.
36
+ return "Table actions";
40
37
  const noun = resolveNoun(count, resultNoun || true);
41
- return ` (${formatCount(count)} selected ${noun})`;
38
+ return `Actions for ${formatCount(count)} selected ${noun}`;
42
39
  }
43
40
 
44
41
  export { TableActions };
@@ -1 +1 @@
1
- {"version":3,"file":"TableActions.js","sources":["../../../src/components/DataTable/TableActions.tsx"],"sourcesContent":["import { IconButton } from \"@components/button\"\nimport { ButtonGroup } from \"@components/button-group\"\nimport React, { type ReactNode } from \"react\"\n\nimport { formatCount, resolveNoun, type ResultNoun } from \"./ResultsCount\"\nimport {\n type DataTableSelection,\n useDataTableSelectionContext,\n} from \"./useDataTableSelection\"\n\n/**\n * A table action rendered as an `IconButton` in the button group above the\n * table. Replaces the original RFC's `{ buttonProps; callback }` shape with a\n * narrower, more controllable API so the design can evolve without exposing the\n * full button surface.\n */\nexport type TableAction<\n SelectionValue extends DataTableSelection = (number | string)[],\n> = {\n /** Called with the current selection when the action is triggered. */\n callback?: (selection: SelectionValue) => void\n /** Whether the action's button is disabled. */\n disabled?: boolean\n /** The icon rendered inside the action's icon button. */\n icon: ReactNode\n /** Accessible label for the icon-only action button. */\n label: string\n /** Standard click handler, invoked with the click event before `callback`. */\n onClick?: React.MouseEventHandler<HTMLButtonElement>\n}\n\nexport interface TableActionsProps {\n /** The table actions to render as an `IconButton` group. */\n actions: TableAction<DataTableSelection>[]\n /**\n * The noun used to describe the selection in each action's `aria-label`.\n * See {@link ResultNoun}.\n */\n resultNoun?: ResultNoun\n}\n\n/**\n * Renders the table actions as an `IconButton` group displayed directly after\n * the results count, above the table. Each entry becomes an icon button whose\n * `callback` receives the current selection.\n */\nexport const TableActions = ({ actions, resultNoun }: TableActionsProps) => {\n const { selectedCount, selection } = useDataTableSelectionContext()\n // The count/noun suffix is the same for every table action, so compute it once\n // here rather than per-button inside the map below.\n const countSuffix = getTableActionCountSuffix(selectedCount, resultNoun)\n\n return (\n <ButtonGroup aria-label=\"Table actions\">\n {actions.map(({ callback, disabled, icon, label, onClick }) => (\n <IconButton\n key={label}\n aria-label={`${label}${countSuffix}`}\n disabled={disabled}\n icon={icon}\n onClick={(event) => {\n onClick?.(event)\n callback?.(selection)\n }}\n tooltip={label}\n tooltipPlacement=\"bottom\"\n />\n ))}\n </ButtonGroup>\n )\n}\n\nTableActions.displayName = \"TableActions\"\n\n/**\n * The count/noun suffix appended to each table action's `aria-label` when rows\n * are selected, e.g. `\" (2 selected people)\"` — so `\"Email\"` reads as\n * `\"Email (2 selected people)\"`. Empty when nothing is selected. Falls back to\n * the default `\"result\"` noun when `resultNoun` isn't provided. Shared across\n * every action, so it's computed once rather than per-button.\n */\nfunction getTableActionCountSuffix(\n count: number,\n resultNoun: ResultNoun | undefined\n): string {\n if (!count) return \"\"\n // An absent or `true` noun both default to `\"result\"`/`\"results\"`.\n const noun = resolveNoun(count, resultNoun || true)\n return ` (${formatCount(count)} selected ${noun})`\n}\n"],"names":["React"],"mappings":";;;;;;;;;;;;AAyCA;;;;AAIG;AACI,MAAM,YAAY,GAAG,CAAC,EAAE,OAAO,EAAE,UAAU,EAAqB,KAAI;IACzE,MAAM,EAAE,aAAa,EAAE,SAAS,EAAE,GAAG,4BAA4B,EAAE;;;IAGnE,MAAM,WAAW,GAAG,yBAAyB,CAAC,aAAa,EAAE,UAAU,CAAC;IAExE,QACEA,cAAA,CAAA,aAAA,CAAC,WAAW,EAAA,EAAA,YAAA,EAAY,eAAe,IACpC,OAAO,CAAC,GAAG,CAAC,CAAC,EAAE,QAAQ,EAAE,QAAQ,EAAE,IAAI,EAAE,KAAK,EAAE,OAAO,EAAE,MACxDA,6BAAC,UAAU,EAAA,EACT,GAAG,EAAE,KAAK,EAAA,YAAA,EACE,GAAG,KAAK,CAAA,EAAG,WAAW,CAAA,CAAE,EACpC,QAAQ,EAAE,QAAQ,EAClB,IAAI,EAAE,IAAI,EACV,OAAO,EAAE,CAAC,KAAK,KAAI;AACjB,YAAA,OAAO,GAAG,KAAK,CAAC;AAChB,YAAA,QAAQ,GAAG,SAAS,CAAC;AACvB,QAAA,CAAC,EACD,OAAO,EAAE,KAAK,EACd,gBAAgB,EAAC,QAAQ,EAAA,CACzB,CACH,CAAC,CACU;AAElB;AAEA,YAAY,CAAC,WAAW,GAAG,cAAc;AAEzC;;;;;;AAMG;AACH,SAAS,yBAAyB,CAChC,KAAa,EACb,UAAkC,EAAA;AAElC,IAAA,IAAI,CAAC,KAAK;AAAE,QAAA,OAAO,EAAE;;IAErB,MAAM,IAAI,GAAG,WAAW,CAAC,KAAK,EAAE,UAAU,IAAI,IAAI,CAAC;IACnD,OAAO,CAAA,EAAA,EAAK,WAAW,CAAC,KAAK,CAAC,CAAA,UAAA,EAAa,IAAI,GAAG;AACpD;;;;"}
1
+ {"version":3,"file":"TableActions.js","sources":["../../../src/components/DataTable/TableActions.tsx"],"sourcesContent":["import { IconButton } from \"@components/button\"\nimport { ButtonGroup } from \"@components/button-group\"\nimport React, { type ReactNode } from \"react\"\n\nimport { formatCount, resolveNoun, type ResultNoun } from \"./ResultsCount\"\nimport {\n type DataTableSelection,\n useDataTableSelectionContext,\n} from \"./useDataTableSelection\"\n\n/**\n * A table action rendered as an `IconButton` in the button group above the\n * table. Replaces the original RFC's `{ buttonProps; callback }` shape with a\n * narrower, more controllable API so the design can evolve without exposing the\n * full button surface.\n */\nexport type TableAction<\n SelectionValue extends DataTableSelection = (number | string)[],\n> = {\n /** Called with the current selection when the action is triggered. */\n callback?: (selection: SelectionValue) => void\n /** Whether the action's button is disabled. */\n disabled?: boolean\n /** The icon rendered inside the action's icon button. */\n icon: ReactNode\n /** Accessible label for the icon-only action button. */\n label: string\n /** Standard click handler, invoked with the click event before `callback`. */\n onClick?: React.MouseEventHandler<HTMLButtonElement>\n}\n\nexport interface TableActionsProps {\n /** The table actions to render as an `IconButton` group. */\n actions: TableAction<DataTableSelection>[]\n /**\n * The noun used to describe the selection in the group's `aria-label`.\n * See {@link ResultNoun}.\n */\n resultNoun?: ResultNoun\n}\n\n/**\n * Renders the table actions as an `IconButton` group displayed directly after\n * the results count, above the table. Each entry becomes an icon button whose\n * `callback` receives the current selection. The group's label carries the\n * selected count, so screen readers announce it once on entering the group\n * rather than on every button.\n */\nexport const TableActions = ({ actions, resultNoun }: TableActionsProps) => {\n const { selectedCount, selection } = useDataTableSelectionContext()\n\n return (\n <ButtonGroup\n aria-label={getTableActionsGroupLabel(selectedCount, resultNoun)}\n >\n {actions.map(({ callback, disabled, icon, label, onClick }) => (\n <IconButton\n key={label}\n aria-label={label}\n disabled={disabled}\n icon={icon}\n onClick={(event) => {\n onClick?.(event)\n callback?.(selection)\n }}\n tooltip={label}\n tooltipPlacement=\"bottom\"\n />\n ))}\n </ButtonGroup>\n )\n}\n\nTableActions.displayName = \"TableActions\"\n\n/**\n * The table actions group's `aria-label`, e.g. `\"Actions for 2 selected\n * people\"` when rows are selected, or `\"Table actions\"` when nothing is\n * selected. Falls back to the default `\"result\"` noun when `resultNoun` isn't\n * provided.\n */\nfunction getTableActionsGroupLabel(\n count: number,\n resultNoun: ResultNoun | undefined\n): string {\n if (!count) return \"Table actions\"\n const noun = resolveNoun(count, resultNoun || true)\n return `Actions for ${formatCount(count)} selected ${noun}`\n}\n"],"names":["React"],"mappings":";;;;;;;;;;;;AAyCA;;;;;;AAMG;AACI,MAAM,YAAY,GAAG,CAAC,EAAE,OAAO,EAAE,UAAU,EAAqB,KAAI;IACzE,MAAM,EAAE,aAAa,EAAE,SAAS,EAAE,GAAG,4BAA4B,EAAE;IAEnE,QACEA,cAAA,CAAA,aAAA,CAAC,WAAW,EAAA,EAAA,YAAA,EACE,yBAAyB,CAAC,aAAa,EAAE,UAAU,CAAC,EAAA,EAE/D,OAAO,CAAC,GAAG,CAAC,CAAC,EAAE,QAAQ,EAAE,QAAQ,EAAE,IAAI,EAAE,KAAK,EAAE,OAAO,EAAE,MACxDA,cAAA,CAAA,aAAA,CAAC,UAAU,IACT,GAAG,EAAE,KAAK,EAAA,YAAA,EACE,KAAK,EACjB,QAAQ,EAAE,QAAQ,EAClB,IAAI,EAAE,IAAI,EACV,OAAO,EAAE,CAAC,KAAK,KAAI;AACjB,YAAA,OAAO,GAAG,KAAK,CAAC;AAChB,YAAA,QAAQ,GAAG,SAAS,CAAC;AACvB,QAAA,CAAC,EACD,OAAO,EAAE,KAAK,EACd,gBAAgB,EAAC,QAAQ,EAAA,CACzB,CACH,CAAC,CACU;AAElB;AAEA,YAAY,CAAC,WAAW,GAAG,cAAc;AAEzC;;;;;AAKG;AACH,SAAS,yBAAyB,CAChC,KAAa,EACb,UAAkC,EAAA;AAElC,IAAA,IAAI,CAAC,KAAK;AAAE,QAAA,OAAO,eAAe;IAClC,MAAM,IAAI,GAAG,WAAW,CAAC,KAAK,EAAE,UAAU,IAAI,IAAI,CAAC;IACnD,OAAO,CAAA,YAAA,EAAe,WAAW,CAAC,KAAK,CAAC,CAAA,UAAA,EAAa,IAAI,EAAE;AAC7D;;;;"}
@@ -14,4 +14,6 @@ export type { PresenceActiveFilter, PresenceFilterConfig, PresenceFilterValue, P
14
14
  export type { SavedView, StaticView } from "./savedViews";
15
15
  export type { ScopedFilterConfig, ScopedFilterOptions } from "./scopedFilter";
16
16
  export type { TextActiveFilter, TextFilterValue, TextOperatorName, } from "./textFilter";
17
+ export type { ApiClient, UseSavedViewsClientOptions, } from "./useSavedViewsClient";
18
+ export { useSavedViewsClient } from "./useSavedViewsClient";
17
19
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/components/DataTable/index.ts"],"names":[],"mappings":"AAAA,OAAO,aAAa,CAAA;AACpB,OAAO,eAAe,CAAA;AAEtB,YAAY,EAAE,qBAAqB,EAAE,MAAM,2BAA2B,CAAA;AACtE,YAAY,EACV,sBAAsB,EACtB,sBAAsB,GACvB,MAAM,oBAAoB,CAAA;AAC3B,YAAY,EACV,qBAAqB,EACrB,qBAAqB,EACrB,cAAc,EACd,kBAAkB,EAClB,IAAI,GACL,MAAM,aAAa,CAAA;AACpB,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAA;AACvC,YAAY,EACV,aAAa,EACb,cAAc,EACd,YAAY,EACZ,eAAe,EACf,oBAAoB,EACpB,mBAAmB,EACnB,UAAU,EACV,cAAc,EACd,UAAU,EACV,YAAY,EACZ,YAAY,GACb,MAAM,mBAAmB,CAAA;AAC1B,YAAY,EACV,gBAAgB,EAChB,eAAe,EACf,gBAAgB,GACjB,MAAM,cAAc,CAAA;AACrB,YAAY,EACV,eAAe,EACf,cAAc,EACd,eAAe,GAChB,MAAM,aAAa,CAAA;AACpB,cAAc,WAAW,CAAA;AACzB,YAAY,EACV,YAAY,EACZ,iBAAiB,EACjB,gBAAgB,EAChB,UAAU,EACV,eAAe,EACf,cAAc,EACd,gBAAgB,EAChB,QAAQ,GACT,MAAM,eAAe,CAAA;AACtB,YAAY,EACV,kBAAkB,EAClB,iBAAiB,EACjB,kBAAkB,GACnB,MAAM,gBAAgB,CAAA;AACvB,YAAY,EACV,oBAAoB,EACpB,oBAAoB,EACpB,mBAAmB,EACnB,oBAAoB,GACrB,MAAM,kBAAkB,CAAA;AACzB,YAAY,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,cAAc,CAAA;AACzD,YAAY,EAAE,kBAAkB,EAAE,mBAAmB,EAAE,MAAM,gBAAgB,CAAA;AAC7E,YAAY,EACV,gBAAgB,EAChB,eAAe,EACf,gBAAgB,GACjB,MAAM,cAAc,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/components/DataTable/index.ts"],"names":[],"mappings":"AAAA,OAAO,aAAa,CAAA;AACpB,OAAO,eAAe,CAAA;AAEtB,YAAY,EAAE,qBAAqB,EAAE,MAAM,2BAA2B,CAAA;AACtE,YAAY,EACV,sBAAsB,EACtB,sBAAsB,GACvB,MAAM,oBAAoB,CAAA;AAC3B,YAAY,EACV,qBAAqB,EACrB,qBAAqB,EACrB,cAAc,EACd,kBAAkB,EAClB,IAAI,GACL,MAAM,aAAa,CAAA;AACpB,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAA;AACvC,YAAY,EACV,aAAa,EACb,cAAc,EACd,YAAY,EACZ,eAAe,EACf,oBAAoB,EACpB,mBAAmB,EACnB,UAAU,EACV,cAAc,EACd,UAAU,EACV,YAAY,EACZ,YAAY,GACb,MAAM,mBAAmB,CAAA;AAC1B,YAAY,EACV,gBAAgB,EAChB,eAAe,EACf,gBAAgB,GACjB,MAAM,cAAc,CAAA;AACrB,YAAY,EACV,eAAe,EACf,cAAc,EACd,eAAe,GAChB,MAAM,aAAa,CAAA;AACpB,cAAc,WAAW,CAAA;AACzB,YAAY,EACV,YAAY,EACZ,iBAAiB,EACjB,gBAAgB,EAChB,UAAU,EACV,eAAe,EACf,cAAc,EACd,gBAAgB,EAChB,QAAQ,GACT,MAAM,eAAe,CAAA;AACtB,YAAY,EACV,kBAAkB,EAClB,iBAAiB,EACjB,kBAAkB,GACnB,MAAM,gBAAgB,CAAA;AACvB,YAAY,EACV,oBAAoB,EACpB,oBAAoB,EACpB,mBAAmB,EACnB,oBAAoB,GACrB,MAAM,kBAAkB,CAAA;AACzB,YAAY,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,cAAc,CAAA;AACzD,YAAY,EAAE,kBAAkB,EAAE,mBAAmB,EAAE,MAAM,gBAAgB,CAAA;AAC7E,YAAY,EACV,gBAAgB,EAChB,eAAe,EACf,gBAAgB,GACjB,MAAM,cAAc,CAAA;AACrB,YAAY,EACV,SAAS,EACT,0BAA0B,GAC3B,MAAM,uBAAuB,CAAA;AAC9B,OAAO,EAAE,mBAAmB,EAAE,MAAM,uBAAuB,CAAA"}
@@ -0,0 +1,3 @@
1
+ /** The rejection's message, else a generic one. */
2
+ export declare function saveErrorMessage(error: unknown): string;
3
+ //# sourceMappingURL=saveErrorMessage.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"saveErrorMessage.d.ts","sourceRoot":"","sources":["../../../src/components/DataTable/saveErrorMessage.ts"],"names":[],"mappings":"AAEA,mDAAmD;AACnD,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,OAAO,UAG9C"}
@@ -0,0 +1,9 @@
1
+ const DEFAULT_MESSAGE = "Your change couldn't be saved. Try again.";
2
+ /** The rejection's message, else a generic one. */
3
+ function saveErrorMessage(error) {
4
+ const message = error?.message;
5
+ return typeof message === "string" && message ? message : DEFAULT_MESSAGE;
6
+ }
7
+
8
+ export { saveErrorMessage };
9
+ //# sourceMappingURL=saveErrorMessage.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"saveErrorMessage.js","sources":["../../../src/components/DataTable/saveErrorMessage.ts"],"sourcesContent":["const DEFAULT_MESSAGE = \"Your change couldn't be saved. Try again.\"\n\n/** The rejection's message, else a generic one. */\nexport function saveErrorMessage(error: unknown) {\n const message = (error as { message?: unknown } | null)?.message\n return typeof message === \"string\" && message ? message : DEFAULT_MESSAGE\n}\n"],"names":[],"mappings":"AAAA,MAAM,eAAe,GAAG,2CAA2C;AAEnE;AACM,SAAU,gBAAgB,CAAC,KAAc,EAAA;AAC7C,IAAA,MAAM,OAAO,GAAI,KAAsC,EAAE,OAAO;AAChE,IAAA,OAAO,OAAO,OAAO,KAAK,QAAQ,IAAI,OAAO,GAAG,OAAO,GAAG,eAAe;AAC3E;;;;"}