@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,32 @@
1
+ import React from "react";
2
+ import type { SavedView } from "./savedViews";
3
+ /** Tracks saves of views not in the list yet, which have no id to go by. */
4
+ export declare const NEW_VIEW: unique symbol;
5
+ type SaveStatusKey = SavedView["id"] | typeof NEW_VIEW;
6
+ type SaveStatus = {
7
+ message: string;
8
+ status: "failed";
9
+ } | {
10
+ status: "saving";
11
+ };
12
+ /**
13
+ * Tracks saved view saves, by view. A save shows a spinner while it's
14
+ * pending, which fades in after 500ms so quick saves show nothing. A failed
15
+ * one shows a "not saved" icon for 3s and is announced to screen readers by
16
+ * the view's `name`. A newer save of the same view replaces the older one's.
17
+ */
18
+ export declare function useSaveStatus(): {
19
+ statusFor: (id: SaveStatusKey) => SaveStatus | undefined;
20
+ track: (id: SaveStatusKey, saving: unknown, name: string) => Promise<void>;
21
+ };
22
+ /**
23
+ * Hidden from screen readers, which hear failures announced instead, so it
24
+ * stays out of the view's name. With a `label`, a failure shows it next to
25
+ * the icon.
26
+ */
27
+ export declare function SaveStatusIcon({ label, status, }: {
28
+ label?: string;
29
+ status?: SaveStatus;
30
+ }): React.JSX.Element | null;
31
+ export {};
32
+ //# sourceMappingURL=useSaveStatus.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useSaveStatus.d.ts","sourceRoot":"","sources":["../../../src/components/DataTable/useSaveStatus.tsx"],"names":[],"mappings":"AAGA,OAAO,KAA2B,MAAM,OAAO,CAAA;AAE/C,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,cAAc,CAAA;AAK7C,4EAA4E;AAC5E,eAAO,MAAM,QAAQ,eAAqB,CAAA;AAE1C,KAAK,aAAa,GAAG,SAAS,CAAC,IAAI,CAAC,GAAG,OAAO,QAAQ,CAAA;AAEtD,KAAK,UAAU,GAAG;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,QAAQ,CAAA;CAAE,GAAG;IAAE,MAAM,EAAE,QAAQ,CAAA;CAAE,CAAA;AAI9E;;;;;GAKG;AACH,wBAAgB,aAAa;oBAyCF,aAAa;gBA1Bb,aAAa,UAAU,OAAO,QAAQ,MAAM;EA2BtE;AAED;;;;GAIG;AACH,wBAAgB,cAAc,CAAC,EAC7B,KAAK,EACL,MAAM,GACP,EAAE;IACD,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,MAAM,CAAC,EAAE,UAAU,CAAA;CACpB,4BAgCA"}
@@ -0,0 +1,80 @@
1
+ import LoadingSpinner from '../internal/LoadingSpinner.js';
2
+ import '../internal/LoadingAnnouncement.js';
3
+ import '../internal/tooltip/Tooltip.js';
4
+ import Icon from '../../utilities/Icon.js';
5
+ import { useAnnounce } from '../../utilities/useAnnounce.js';
6
+ import React__default, { useState, useRef } from 'react';
7
+ import { saveErrorMessage } from './saveErrorMessage.js';
8
+
9
+ const FAILED_DURATION = 3000;
10
+ /** Tracks saves of views not in the list yet, which have no id to go by. */
11
+ const NEW_VIEW = Symbol("new view");
12
+ const wait = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
13
+ /**
14
+ * Tracks saved view saves, by view. A save shows a spinner while it's
15
+ * pending, which fades in after 500ms so quick saves show nothing. A failed
16
+ * one shows a "not saved" icon for 3s and is announced to screen readers by
17
+ * the view's `name`. A newer save of the same view replaces the older one's.
18
+ */
19
+ function useSaveStatus() {
20
+ const announce = useAnnounce();
21
+ const [statuses, setStatuses] = useState(() => new Map());
22
+ const latestSave = useRef(new Map());
23
+ const setStatus = (id, status) => setStatuses((current) => {
24
+ const next = new Map(current);
25
+ if (status)
26
+ next.set(id, status);
27
+ else
28
+ next.delete(id);
29
+ return next;
30
+ });
31
+ const track = async (id, saving, name) => {
32
+ const save = (latestSave.current.get(id) ?? 0) + 1;
33
+ latestSave.current.set(id, save);
34
+ const isLatest = () => latestSave.current.get(id) === save;
35
+ setStatus(id, { status: "saving" });
36
+ let failure;
37
+ try {
38
+ await saving;
39
+ }
40
+ catch (error) {
41
+ failure = { error };
42
+ }
43
+ if (!isLatest())
44
+ return;
45
+ if (!failure) {
46
+ setStatus(id);
47
+ return;
48
+ }
49
+ const message = saveErrorMessage(failure.error);
50
+ setStatus(id, { message, status: "failed" });
51
+ announce(`${name} not saved. ${message}`);
52
+ await wait(FAILED_DURATION);
53
+ if (isLatest())
54
+ setStatus(id);
55
+ };
56
+ return { statusFor: (id) => statuses.get(id), track };
57
+ }
58
+ /**
59
+ * Hidden from screen readers, which hear failures announced instead, so it
60
+ * stays out of the view's name. With a `label`, a failure shows it next to
61
+ * the icon.
62
+ */
63
+ function SaveStatusIcon({ label, status, }) {
64
+ if (!status)
65
+ return null;
66
+ if (status.status === "saving") {
67
+ return (React__default.createElement("span", { "aria-hidden": true, className: "tds-data-table-saved-view-save-status tds-data-table-saved-view-save-status--saving" },
68
+ React__default.createElement(LoadingSpinner, null)));
69
+ }
70
+ const icon = (React__default.createElement("span", { "aria-hidden": true, className: "tds-data-table-saved-view-save-status tds-data-table-saved-view-save-status--failed", title: `Not saved. ${status.message}` },
71
+ React__default.createElement(Icon, { "aria-hidden": true, symbol: "general#exclamation-triangle" })));
72
+ if (!label)
73
+ return icon;
74
+ return (React__default.createElement("span", { "aria-hidden": true, className: "tds-data-table-saved-view-save-error", title: status.message },
75
+ icon,
76
+ label));
77
+ }
78
+
79
+ export { NEW_VIEW, SaveStatusIcon, useSaveStatus };
80
+ //# sourceMappingURL=useSaveStatus.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useSaveStatus.js","sources":["../../../src/components/DataTable/useSaveStatus.tsx"],"sourcesContent":["import { LoadingSpinner } from \"@components/internal\"\nimport Icon from \"@utilities/Icon\"\nimport { useAnnounce } from \"@utilities/useAnnounce\"\nimport React, { useRef, useState } from \"react\"\n\nimport type { SavedView } from \"./savedViews\"\nimport { saveErrorMessage } from \"./saveErrorMessage\"\n\nconst FAILED_DURATION = 3000\n\n/** Tracks saves of views not in the list yet, which have no id to go by. */\nexport const NEW_VIEW = Symbol(\"new view\")\n\ntype SaveStatusKey = SavedView[\"id\"] | typeof NEW_VIEW\n\ntype SaveStatus = { message: string; status: \"failed\" } | { status: \"saving\" }\n\nconst wait = (ms: number) => new Promise((resolve) => setTimeout(resolve, ms))\n\n/**\n * Tracks saved view saves, by view. A save shows a spinner while it's\n * pending, which fades in after 500ms so quick saves show nothing. A failed\n * one shows a \"not saved\" icon for 3s and is announced to screen readers by\n * the view's `name`. A newer save of the same view replaces the older one's.\n */\nexport function useSaveStatus() {\n const announce = useAnnounce()\n const [statuses, setStatuses] = useState(\n () => new Map<SaveStatusKey, SaveStatus>()\n )\n const latestSave = useRef(new Map<SaveStatusKey, number>())\n\n const setStatus = (id: SaveStatusKey, status?: SaveStatus) =>\n setStatuses((current) => {\n const next = new Map(current)\n if (status) next.set(id, status)\n else next.delete(id)\n return next\n })\n\n const track = async (id: SaveStatusKey, saving: unknown, name: string) => {\n const save = (latestSave.current.get(id) ?? 0) + 1\n latestSave.current.set(id, save)\n const isLatest = () => latestSave.current.get(id) === save\n\n setStatus(id, { status: \"saving\" })\n\n let failure: { error: unknown } | undefined\n try {\n await saving\n } catch (error) {\n failure = { error }\n }\n if (!isLatest()) return\n if (!failure) {\n setStatus(id)\n return\n }\n\n const message = saveErrorMessage(failure.error)\n setStatus(id, { message, status: \"failed\" })\n announce(`${name} not saved. ${message}`)\n await wait(FAILED_DURATION)\n if (isLatest()) setStatus(id)\n }\n\n return { statusFor: (id: SaveStatusKey) => statuses.get(id), track }\n}\n\n/**\n * Hidden from screen readers, which hear failures announced instead, so it\n * stays out of the view's name. With a `label`, a failure shows it next to\n * the icon.\n */\nexport function SaveStatusIcon({\n label,\n status,\n}: {\n label?: string\n status?: SaveStatus\n}) {\n if (!status) return null\n if (status.status === \"saving\") {\n return (\n <span\n aria-hidden\n className=\"tds-data-table-saved-view-save-status tds-data-table-saved-view-save-status--saving\"\n >\n <LoadingSpinner />\n </span>\n )\n }\n const icon = (\n <span\n aria-hidden\n className=\"tds-data-table-saved-view-save-status tds-data-table-saved-view-save-status--failed\"\n title={`Not saved. ${status.message}`}\n >\n <Icon aria-hidden symbol=\"general#exclamation-triangle\" />\n </span>\n )\n if (!label) return icon\n return (\n <span\n aria-hidden\n className=\"tds-data-table-saved-view-save-error\"\n title={status.message}\n >\n {icon}\n {label}\n </span>\n )\n}\n"],"names":["React"],"mappings":"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"}
@@ -0,0 +1,14 @@
1
+ import type { NewSavedViewModalProps } from "./NewSavedViewModal";
2
+ import { type SavedView } from "./savedViews";
3
+ /**
4
+ * The name modal's state, for a new view, a duplicate, or a rename. Spread
5
+ * `modalProps` onto a `NewSavedViewModal`. What it saves outlives the modal's
6
+ * open state, so the title holds while the modal fades out.
7
+ */
8
+ export declare function useSavedViewNameModal(onUpdate?: (savedView: SavedView) => Promise<SavedView | undefined> | SavedView): {
9
+ modalProps: NewSavedViewModalProps;
10
+ open: (title: string, defaultName: string, save: (name: string) => void) => void;
11
+ openDuplicate: (view: SavedView, create: (duplicate: Omit<SavedView, "id">) => void) => void;
12
+ openRename: (view: SavedView, track: (saving: Promise<void>) => void) => void;
13
+ };
14
+ //# sourceMappingURL=useSavedViewNameModal.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useSavedViewNameModal.d.ts","sourceRoot":"","sources":["../../../src/components/DataTable/useSavedViewNameModal.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,qBAAqB,CAAA;AACjE,OAAO,EAAE,KAAK,SAAS,EAAsB,MAAM,cAAc,CAAA;AAGjE;;;;GAIG;AACH,wBAAgB,qBAAqB,CACnC,QAAQ,CAAC,EAAE,CACT,SAAS,EAAE,SAAS,KACjB,OAAO,CAAC,SAAS,GAAG,SAAS,CAAC,GAAG,SAAS;;kBAWtC,MAAM,eACA,MAAM,QACb,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI;0BAQtB,SAAS,UACP,CAAC,SAAS,EAAE,IAAI,CAAC,SAAS,EAAE,IAAI,CAAC,KAAK,IAAI;uBAS5C,SAAS,SACR,CAAC,MAAM,EAAE,OAAO,CAAC,IAAI,CAAC,KAAK,IAAI;EAmBzC"}
@@ -0,0 +1,43 @@
1
+ import { useState } from 'react';
2
+ import { savedViewDuplicate } from './savedViews.js';
3
+ import { useUpdateSavedViewName } from './useUpdateSavedViewName.js';
4
+
5
+ /**
6
+ * The name modal's state, for a new view, a duplicate, or a rename. Spread
7
+ * `modalProps` onto a `NewSavedViewModal`. What it saves outlives the modal's
8
+ * open state, so the title holds while the modal fades out.
9
+ */
10
+ function useSavedViewNameModal(onUpdate) {
11
+ const [draft, setDraft] = useState();
12
+ const [isOpen, setIsOpen] = useState(false);
13
+ const updateSavedViewName = useUpdateSavedViewName(onUpdate);
14
+ const open = (title, defaultName, save) => {
15
+ setDraft({ defaultName, save, title });
16
+ setIsOpen(true);
17
+ };
18
+ /** `create` gets the duplicate under the entered name, without an id. */
19
+ const openDuplicate = (view, create) => {
20
+ open("Duplicate view", `${view.name} copy`, (name) => create(savedViewDuplicate(view, name)));
21
+ };
22
+ /** `track` gets the rename's save. */
23
+ const openRename = (view, track) => {
24
+ open("Rename view", view.name, (name) => {
25
+ if (name !== view.name)
26
+ track(updateSavedViewName(view, name));
27
+ });
28
+ };
29
+ const modalProps = {
30
+ defaultName: draft?.defaultName,
31
+ onClose: () => setIsOpen(false),
32
+ onSave: (name) => {
33
+ setIsOpen(false);
34
+ draft?.save(name);
35
+ },
36
+ open: isOpen,
37
+ title: draft?.title,
38
+ };
39
+ return { modalProps, open, openDuplicate, openRename };
40
+ }
41
+
42
+ export { useSavedViewNameModal };
43
+ //# sourceMappingURL=useSavedViewNameModal.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useSavedViewNameModal.js","sources":["../../../src/components/DataTable/useSavedViewNameModal.ts"],"sourcesContent":["import { useState } from \"react\"\n\nimport type { NewSavedViewModalProps } from \"./NewSavedViewModal\"\nimport { type SavedView, savedViewDuplicate } from \"./savedViews\"\nimport { useUpdateSavedViewName } from \"./useUpdateSavedViewName\"\n\n/**\n * The name modal's state, for a new view, a duplicate, or a rename. Spread\n * `modalProps` onto a `NewSavedViewModal`. What it saves outlives the modal's\n * open state, so the title holds while the modal fades out.\n */\nexport function useSavedViewNameModal(\n onUpdate?: (\n savedView: SavedView\n ) => Promise<SavedView | undefined> | SavedView\n) {\n const [draft, setDraft] = useState<{\n defaultName: string\n save: (name: string) => void\n title: string\n }>()\n const [isOpen, setIsOpen] = useState(false)\n const updateSavedViewName = useUpdateSavedViewName(onUpdate)\n\n const open = (\n title: string,\n defaultName: string,\n save: (name: string) => void\n ) => {\n setDraft({ defaultName, save, title })\n setIsOpen(true)\n }\n\n /** `create` gets the duplicate under the entered name, without an id. */\n const openDuplicate = (\n view: SavedView,\n create: (duplicate: Omit<SavedView, \"id\">) => void\n ) => {\n open(\"Duplicate view\", `${view.name} copy`, (name) =>\n create(savedViewDuplicate(view, name))\n )\n }\n\n /** `track` gets the rename's save. */\n const openRename = (\n view: SavedView,\n track: (saving: Promise<void>) => void\n ) => {\n open(\"Rename view\", view.name, (name) => {\n if (name !== view.name) track(updateSavedViewName(view, name))\n })\n }\n\n const modalProps: NewSavedViewModalProps = {\n defaultName: draft?.defaultName,\n onClose: () => setIsOpen(false),\n onSave: (name) => {\n setIsOpen(false)\n draft?.save(name)\n },\n open: isOpen,\n title: draft?.title,\n }\n\n return { modalProps, open, openDuplicate, openRename }\n}\n"],"names":[],"mappings":";;;;AAMA;;;;AAIG;AACG,SAAU,qBAAqB,CACnC,QAE+C,EAAA;IAE/C,MAAM,CAAC,KAAK,EAAE,QAAQ,CAAC,GAAG,QAAQ,EAI9B;IACJ,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,GAAG,QAAQ,CAAC,KAAK,CAAC;AAC3C,IAAA,MAAM,mBAAmB,GAAG,sBAAsB,CAAC,QAAQ,CAAC;IAE5D,MAAM,IAAI,GAAG,CACX,KAAa,EACb,WAAmB,EACnB,IAA4B,KAC1B;QACF,QAAQ,CAAC,EAAE,WAAW,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC;QACtC,SAAS,CAAC,IAAI,CAAC;AACjB,IAAA,CAAC;;AAGD,IAAA,MAAM,aAAa,GAAG,CACpB,IAAe,EACf,MAAkD,KAChD;QACF,IAAI,CAAC,gBAAgB,EAAE,CAAA,EAAG,IAAI,CAAC,IAAI,CAAA,KAAA,CAAO,EAAE,CAAC,IAAI,KAC/C,MAAM,CAAC,kBAAkB,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC,CACvC;AACH,IAAA,CAAC;;AAGD,IAAA,MAAM,UAAU,GAAG,CACjB,IAAe,EACf,KAAsC,KACpC;QACF,IAAI,CAAC,aAAa,EAAE,IAAI,CAAC,IAAI,EAAE,CAAC,IAAI,KAAI;AACtC,YAAA,IAAI,IAAI,KAAK,IAAI,CAAC,IAAI;gBAAE,KAAK,CAAC,mBAAmB,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;AAChE,QAAA,CAAC,CAAC;AACJ,IAAA,CAAC;AAED,IAAA,MAAM,UAAU,GAA2B;QACzC,WAAW,EAAE,KAAK,EAAE,WAAW;AAC/B,QAAA,OAAO,EAAE,MAAM,SAAS,CAAC,KAAK,CAAC;AAC/B,QAAA,MAAM,EAAE,CAAC,IAAI,KAAI;YACf,SAAS,CAAC,KAAK,CAAC;AAChB,YAAA,KAAK,EAAE,IAAI,CAAC,IAAI,CAAC;QACnB,CAAC;AACD,QAAA,IAAI,EAAE,MAAM;QACZ,KAAK,EAAE,KAAK,EAAE,KAAK;KACpB;IAED,OAAO,EAAE,UAAU,EAAE,IAAI,EAAE,aAAa,EAAE,UAAU,EAAE;AACxD;;;;"}
@@ -0,0 +1,58 @@
1
+ import { type SavedView } from "./savedViews";
2
+ /**
3
+ * Sends requests to the saved views API. Matches
4
+ * `@planningcenter/api-client`'s `Client`, so auth, CSRF, and the API root stay
5
+ * in the app; pass one whose root serves the private graph. Each method
6
+ * resolves to the parsed response and rejects on failure.
7
+ */
8
+ export interface ApiClient {
9
+ delete(request: {
10
+ url: string;
11
+ }): Promise<unknown>;
12
+ patch(request: {
13
+ data: object;
14
+ url: string;
15
+ }): Promise<unknown>;
16
+ post(request: {
17
+ data: object;
18
+ url: string;
19
+ }): Promise<unknown>;
20
+ }
21
+ export interface UseSavedViewsClientOptions {
22
+ client: ApiClient;
23
+ tableKey: string;
24
+ }
25
+ /**
26
+ * Returns DataTable's saved view callbacks, sending each change to the saved
27
+ * views endpoints that `tapestry:saved_views` adds to pco-api's private graph:
28
+ *
29
+ * - `POST /data_tables/:table_key/saved_views`
30
+ * - `PATCH /data_tables/:table_key/saved_views/:id` (also takes `after_id` to
31
+ * reorder)
32
+ * - `DELETE /data_tables/:table_key/saved_views/:id`
33
+ * - `POST` and `DELETE /data_tables/:table_key/saved_view_default`
34
+ *
35
+ * Each callback resolves once its request succeeds and rejects with the
36
+ * client's error. Default changes are sent one at a time, so the server keeps
37
+ * the last one chosen. DataTable shows the change right away and undoes it on
38
+ * rejection. Doesn't load views or hold state, so pass `data_table_props` to
39
+ * DataTable too:
40
+ *
41
+ * ```tsx
42
+ * <DataTable {...dataTableProps} {...useSavedViewsClient({ client, tableKey })} />
43
+ * ```
44
+ */
45
+ export declare function useSavedViewsClient({ client, tableKey, }: UseSavedViewsClientOptions): {
46
+ onDefaultViewIdChange: (id: number | string) => Promise<void>;
47
+ onSavedViewCreate: (view: Omit<SavedView, "id">) => Promise<{
48
+ id: string | number;
49
+ sort?: import("./DataTable").Sort | undefined;
50
+ name: string;
51
+ activeFilters: import("./FilterTypes").ActiveFilter[];
52
+ hiddenColumnNames?: string[] | undefined;
53
+ }>;
54
+ onSavedViewDelete: (view: SavedView) => Promise<void>;
55
+ onSavedViewReorder: (view: SavedView, after: SavedView | null) => Promise<void>;
56
+ onSavedViewUpdate: (view: SavedView) => Promise<SavedView>;
57
+ };
58
+ //# sourceMappingURL=useSavedViewsClient.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useSavedViewsClient.d.ts","sourceRoot":"","sources":["../../../src/components/DataTable/useSavedViewsClient.ts"],"names":[],"mappings":"AAGA,OAAO,EAAe,KAAK,SAAS,EAAE,MAAM,cAAc,CAAA;AAE1D;;;;;GAKG;AACH,MAAM,WAAW,SAAS;IACxB,MAAM,CAAC,OAAO,EAAE;QAAE,GAAG,EAAE,MAAM,CAAA;KAAE,GAAG,OAAO,CAAC,OAAO,CAAC,CAAA;IAClD,KAAK,CAAC,OAAO,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,MAAM,CAAA;KAAE,GAAG,OAAO,CAAC,OAAO,CAAC,CAAA;IAC/D,IAAI,CAAC,OAAO,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,MAAM,CAAA;KAAE,GAAG,OAAO,CAAC,OAAO,CAAC,CAAA;CAC/D;AAED,MAAM,WAAW,0BAA0B;IACzC,MAAM,EAAE,SAAS,CAAA;IACjB,QAAQ,EAAE,MAAM,CAAA;CACjB;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,mBAAmB,CAAC,EAClC,MAAM,EACN,QAAQ,GACT,EAAE,0BAA0B;gCA0Cc,MAAM,GAAG,MAAM;8BAnCjB,IAAI,CAAC,SAAS,EAAE,IAAI,CAAC;;;;;;;8BA8BrB,SAAS;+BAdxC,SAAS,SACR,SAAS,GAAG,IAAI;8BARc,SAAS;EA0DjD"}
@@ -0,0 +1,87 @@
1
+ import { useRef } from 'react';
2
+ import { initialView } from './savedViews.js';
3
+
4
+ /**
5
+ * Returns DataTable's saved view callbacks, sending each change to the saved
6
+ * views endpoints that `tapestry:saved_views` adds to pco-api's private graph:
7
+ *
8
+ * - `POST /data_tables/:table_key/saved_views`
9
+ * - `PATCH /data_tables/:table_key/saved_views/:id` (also takes `after_id` to
10
+ * reorder)
11
+ * - `DELETE /data_tables/:table_key/saved_views/:id`
12
+ * - `POST` and `DELETE /data_tables/:table_key/saved_view_default`
13
+ *
14
+ * Each callback resolves once its request succeeds and rejects with the
15
+ * client's error. Default changes are sent one at a time, so the server keeps
16
+ * the last one chosen. DataTable shows the change right away and undoes it on
17
+ * rejection. Doesn't load views or hold state, so pass `data_table_props` to
18
+ * DataTable too:
19
+ *
20
+ * ```tsx
21
+ * <DataTable {...dataTableProps} {...useSavedViewsClient({ client, tableKey })} />
22
+ * ```
23
+ */
24
+ function useSavedViewsClient({ client, tableKey, }) {
25
+ const tableUrl = `/data_tables/${encodeURIComponent(tableKey)}`;
26
+ const viewUrl = (id) => `${tableUrl}/saved_views/${encodeURIComponent(String(id))}`;
27
+ const defaultUrl = `${tableUrl}/saved_view_default`;
28
+ const lastDefaultChange = useRef(Promise.resolve());
29
+ const onSavedViewCreate = async (view) => {
30
+ // Only the id is read, since clients may reshape the response
31
+ const { data } = (await client.post({
32
+ data: savedViewDocument(view),
33
+ url: `${tableUrl}/saved_views`,
34
+ }));
35
+ return { ...view, id: data.id };
36
+ };
37
+ const onSavedViewUpdate = async (view) => {
38
+ await client.patch({ data: savedViewDocument(view), url: viewUrl(view.id) });
39
+ return view;
40
+ };
41
+ /** Places the view after `after`, or first when it's `null`. */
42
+ const onSavedViewReorder = async (view, after) => {
43
+ await client.patch({
44
+ data: {
45
+ data: {
46
+ attributes: { after_id: after?.id ?? null },
47
+ type: "SavedView",
48
+ },
49
+ },
50
+ url: viewUrl(view.id),
51
+ });
52
+ };
53
+ const onSavedViewDelete = async (view) => {
54
+ await client.delete({ url: viewUrl(view.id) });
55
+ };
56
+ /** Pass the initial view's id to reset the default. */
57
+ const onDefaultViewIdChange = async (id) => {
58
+ const send = () => id === initialView.id
59
+ ? client.delete({ url: defaultUrl })
60
+ : client.post({
61
+ data: {
62
+ data: {
63
+ attributes: { view: String(id) },
64
+ type: "SavedViewDefault",
65
+ },
66
+ },
67
+ url: defaultUrl,
68
+ });
69
+ const change = lastDefaultChange.current.then(send, send);
70
+ lastDefaultChange.current = change;
71
+ await change;
72
+ };
73
+ return {
74
+ onDefaultViewIdChange,
75
+ onSavedViewCreate,
76
+ onSavedViewDelete,
77
+ onSavedViewReorder,
78
+ onSavedViewUpdate,
79
+ };
80
+ }
81
+ function savedViewDocument(view) {
82
+ const { id: _id, name, ...state } = view;
83
+ return { data: { attributes: { name, state }, type: "SavedView" } };
84
+ }
85
+
86
+ export { useSavedViewsClient };
87
+ //# sourceMappingURL=useSavedViewsClient.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useSavedViewsClient.js","sources":["../../../src/components/DataTable/useSavedViewsClient.ts"],"sourcesContent":["import { useRef } from \"react\"\n\nimport type { DataTableProps } from \"./DataTable\"\nimport { initialView, type SavedView } from \"./savedViews\"\n\n/**\n * Sends requests to the saved views API. Matches\n * `@planningcenter/api-client`'s `Client`, so auth, CSRF, and the API root stay\n * in the app; pass one whose root serves the private graph. Each method\n * resolves to the parsed response and rejects on failure.\n */\nexport interface ApiClient {\n delete(request: { url: string }): Promise<unknown>\n patch(request: { data: object; url: string }): Promise<unknown>\n post(request: { data: object; url: string }): Promise<unknown>\n}\n\nexport interface UseSavedViewsClientOptions {\n client: ApiClient\n tableKey: string\n}\n\n/**\n * Returns DataTable's saved view callbacks, sending each change to the saved\n * views endpoints that `tapestry:saved_views` adds to pco-api's private graph:\n *\n * - `POST /data_tables/:table_key/saved_views`\n * - `PATCH /data_tables/:table_key/saved_views/:id` (also takes `after_id` to\n * reorder)\n * - `DELETE /data_tables/:table_key/saved_views/:id`\n * - `POST` and `DELETE /data_tables/:table_key/saved_view_default`\n *\n * Each callback resolves once its request succeeds and rejects with the\n * client's error. Default changes are sent one at a time, so the server keeps\n * the last one chosen. DataTable shows the change right away and undoes it on\n * rejection. Doesn't load views or hold state, so pass `data_table_props` to\n * DataTable too:\n *\n * ```tsx\n * <DataTable {...dataTableProps} {...useSavedViewsClient({ client, tableKey })} />\n * ```\n */\nexport function useSavedViewsClient({\n client,\n tableKey,\n}: UseSavedViewsClientOptions) {\n const tableUrl = `/data_tables/${encodeURIComponent(tableKey)}`\n const viewUrl = (id: SavedView[\"id\"]) =>\n `${tableUrl}/saved_views/${encodeURIComponent(String(id))}`\n const defaultUrl = `${tableUrl}/saved_view_default`\n const lastDefaultChange = useRef<Promise<unknown>>(Promise.resolve())\n\n const onSavedViewCreate = async (view: Omit<SavedView, \"id\">) => {\n // Only the id is read, since clients may reshape the response\n const { data } = (await client.post({\n data: savedViewDocument(view),\n url: `${tableUrl}/saved_views`,\n })) as { data: { id: number | string } }\n return { ...view, id: data.id }\n }\n\n const onSavedViewUpdate = async (view: SavedView) => {\n await client.patch({ data: savedViewDocument(view), url: viewUrl(view.id) })\n return view\n }\n\n /** Places the view after `after`, or first when it's `null`. */\n const onSavedViewReorder = async (\n view: SavedView,\n after: SavedView | null\n ) => {\n await client.patch({\n data: {\n data: {\n attributes: { after_id: after?.id ?? null },\n type: \"SavedView\",\n },\n },\n url: viewUrl(view.id),\n })\n }\n\n const onSavedViewDelete = async (view: SavedView) => {\n await client.delete({ url: viewUrl(view.id) })\n }\n\n /** Pass the initial view's id to reset the default. */\n const onDefaultViewIdChange = async (id: number | string) => {\n const send = () =>\n id === initialView.id\n ? client.delete({ url: defaultUrl })\n : client.post({\n data: {\n data: {\n attributes: { view: String(id) },\n type: \"SavedViewDefault\",\n },\n },\n url: defaultUrl,\n })\n const change = lastDefaultChange.current.then(send, send)\n lastDefaultChange.current = change\n await change\n }\n\n return {\n onDefaultViewIdChange,\n onSavedViewCreate,\n onSavedViewDelete,\n onSavedViewReorder,\n onSavedViewUpdate,\n } satisfies Pick<\n DataTableProps,\n | \"onDefaultViewIdChange\"\n | \"onSavedViewCreate\"\n | \"onSavedViewDelete\"\n | \"onSavedViewReorder\"\n | \"onSavedViewUpdate\"\n >\n}\n\nfunction savedViewDocument(view: Omit<SavedView, \"id\">) {\n const { id: _id, name, ...state } = view as SavedView\n return { data: { attributes: { name, state }, type: \"SavedView\" } }\n}\n"],"names":[],"mappings":"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"}
@@ -0,0 +1,35 @@
1
+ import { type SavedView } from "./savedViews";
2
+ interface SavedViewsStateOptions {
3
+ initialDefaultViewId: NonNullable<SavedView["id"]>;
4
+ initialSavedViews: SavedView[] | undefined;
5
+ onCreate?: (savedView: Omit<SavedView, "id">) => Promise<SavedView> | SavedView;
6
+ onDelete?: (savedView: SavedView) => Promise<void> | void;
7
+ onReorder?: (savedView: SavedView, after: SavedView | null) => Promise<void> | void;
8
+ onSetDefault?: (id: NonNullable<SavedView["id"]>) => Promise<void> | void;
9
+ onUpdate?: (savedView: SavedView) => Promise<SavedView> | SavedView;
10
+ }
11
+ /**
12
+ * Keeps the saved views and default view id after mount. Each callback is
13
+ * wrapped to apply its change here, and stays undefined when the consumer's is,
14
+ * since that hides the matching action. Updates, deletes, and default changes
15
+ * show right away and are undone if the callback rejects, unless a newer
16
+ * change has replaced them. Reorders save one at a time, so a failed one puts
17
+ * back the order from before it.
18
+ */
19
+ export declare function useSavedViewsState({ initialDefaultViewId, initialSavedViews, onCreate, onDelete, onReorder, onSetDefault, onUpdate, }: SavedViewsStateOptions): {
20
+ defaultViewId: string | number;
21
+ isReordering: boolean;
22
+ onCreate: ((view: Omit<SavedView, "id">) => Promise<SavedView>) | undefined;
23
+ onDelete: ((view: SavedView) => Promise<void>) | undefined;
24
+ onReorder: ((view: SavedView, target: ReorderTarget) => Promise<void>) | undefined;
25
+ onSetDefault: ((id: NonNullable<SavedView["id"]>) => Promise<void>) | undefined;
26
+ onUpdate: ((view: SavedView) => Promise<SavedView>) | undefined;
27
+ savedViews: SavedView[] | undefined;
28
+ };
29
+ /** Where a view was dropped, as React Aria reports it. */
30
+ export interface ReorderTarget {
31
+ dropPosition: "after" | "before";
32
+ view: SavedView;
33
+ }
34
+ export {};
35
+ //# sourceMappingURL=useSavedViewsState.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useSavedViewsState.d.ts","sourceRoot":"","sources":["../../../src/components/DataTable/useSavedViewsState.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,KAAK,SAAS,EAAiB,MAAM,cAAc,CAAA;AAE5D,UAAU,sBAAsB;IAC9B,oBAAoB,EAAE,WAAW,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,CAAA;IAClD,iBAAiB,EAAE,SAAS,EAAE,GAAG,SAAS,CAAA;IAC1C,QAAQ,CAAC,EAAE,CACT,SAAS,EAAE,IAAI,CAAC,SAAS,EAAE,IAAI,CAAC,KAC7B,OAAO,CAAC,SAAS,CAAC,GAAG,SAAS,CAAA;IACnC,QAAQ,CAAC,EAAE,CAAC,SAAS,EAAE,SAAS,KAAK,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAA;IACzD,SAAS,CAAC,EAAE,CACV,SAAS,EAAE,SAAS,EACpB,KAAK,EAAE,SAAS,GAAG,IAAI,KACpB,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAA;IACzB,YAAY,CAAC,EAAE,CAAC,EAAE,EAAE,WAAW,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,KAAK,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAA;IACzE,QAAQ,CAAC,EAAE,CAAC,SAAS,EAAE,SAAS,KAAK,OAAO,CAAC,SAAS,CAAC,GAAG,SAAS,CAAA;CACpE;AAgCD;;;;;;;GAOG;AACH,wBAAgB,kBAAkB,CAAC,EACjC,oBAAoB,EACpB,iBAAiB,EACjB,QAAQ,EACR,QAAQ,EACR,SAAS,EACT,YAAY,EACZ,QAAQ,GACT,EAAE,sBAAsB;;;sBAwDL,IAAI,CAAC,SAAS,EAAE,IAAI,CAAC;sBASrB,SAAS;uBA6BT,SAAS,UAAU,aAAa;wBA6BlC,WAAW,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC;sBAa1B,SAAS;;EAoB5B;AAED,0DAA0D;AAC1D,MAAM,WAAW,aAAa;IAC5B,YAAY,EAAE,OAAO,GAAG,QAAQ,CAAA;IAChC,IAAI,EAAE,SAAS,CAAA;CAChB"}
@@ -0,0 +1,192 @@
1
+ import { useState, useRef } from 'react';
2
+ import { withoutSearch } from './savedViews.js';
3
+
4
+ function startSaving(updates, view) {
5
+ updates.saving.push(view);
6
+ }
7
+ function stopSaving(updates, view) {
8
+ updates.saving = updates.saving.filter((pending) => pending !== view);
9
+ }
10
+ // A slower save of an older update doesn't replace a newer one.
11
+ function confirmIfNewest(updates, saved, order) {
12
+ if (order <= updates.confirmedOrder)
13
+ return;
14
+ updates.confirmed = saved;
15
+ updates.confirmedOrder = order;
16
+ }
17
+ // The newest update still saving, or else the last saved version.
18
+ function viewToRestore(updates) {
19
+ return updates.saving.at(-1) ?? updates.confirmed;
20
+ }
21
+ /**
22
+ * Keeps the saved views and default view id after mount. Each callback is
23
+ * wrapped to apply its change here, and stays undefined when the consumer's is,
24
+ * since that hides the matching action. Updates, deletes, and default changes
25
+ * show right away and are undone if the callback rejects, unless a newer
26
+ * change has replaced them. Reorders save one at a time, so a failed one puts
27
+ * back the order from before it.
28
+ */
29
+ function useSavedViewsState({ initialDefaultViewId, initialSavedViews, onCreate, onDelete, onReorder, onSetDefault, onUpdate, }) {
30
+ const [savedViews, setSavedViews] = useState(() => initialSavedViews?.map(withoutSearch));
31
+ const [defaultViewId, setDefaultViewId] = useState(initialDefaultViewId);
32
+ const latestDefaultChange = useRef(0);
33
+ const latestUpdate = useRef(0);
34
+ const updates = useRef(new Map());
35
+ const [isReordering, setIsReordering] = useState(false);
36
+ // So a second drop before a render is skipped too.
37
+ const isReorderingNow = useRef(false);
38
+ // Only swaps out `current` if it's still there, so a slow save doesn't
39
+ // overwrite a newer change to the same view.
40
+ const replaceView = (current, next) => setSavedViews((views) => views?.map((view) => (view === current ? next : view)));
41
+ // Starts from the view as it was last saved, to restore if every update fails.
42
+ const trackUpdates = (view) => {
43
+ let tracked = updates.current.get(view.id);
44
+ if (!tracked) {
45
+ const original = savedViews?.find(({ id }) => id === view.id);
46
+ tracked = { confirmed: original ?? view, confirmedOrder: 0, saving: [] };
47
+ updates.current.set(view.id, tracked);
48
+ }
49
+ return tracked;
50
+ };
51
+ const showUpdate = (view) => setSavedViews((views) => views?.map((current) => (current.id === view.id ? view : current)));
52
+ // Returns an undo that does nothing once a newer default has been set.
53
+ const changeDefault = (id) => {
54
+ const change = ++latestDefaultChange.current;
55
+ let previous = id;
56
+ setDefaultViewId((current) => {
57
+ previous = current;
58
+ return id;
59
+ });
60
+ // Read in an updater, since a callback that rejects right away runs this
61
+ // before the change above has been applied.
62
+ return () => {
63
+ if (latestDefaultChange.current === change)
64
+ setDefaultViewId(() => previous);
65
+ };
66
+ };
67
+ return {
68
+ defaultViewId,
69
+ isReordering,
70
+ onCreate: onCreate &&
71
+ (async (view) => {
72
+ const created = await onCreate(view);
73
+ const saved = created && withoutSearch(created);
74
+ // Tolerates a consumer that returns nothing, leaving the list as is.
75
+ if (saved)
76
+ setSavedViews((views = []) => [...views, saved]);
77
+ return saved;
78
+ }),
79
+ onDelete: onDelete &&
80
+ (async (view) => {
81
+ let index = -1;
82
+ let removed;
83
+ setSavedViews((views) => {
84
+ index = views?.findIndex(({ id }) => id === view.id) ?? -1;
85
+ removed = views?.[index];
86
+ return views?.filter(({ id }) => id !== view.id);
87
+ });
88
+ const undoDefault = view.id === defaultViewId ? changeDefault("initial") : undefined;
89
+ try {
90
+ await onDelete(view);
91
+ }
92
+ catch (error) {
93
+ setSavedViews((views) => !views || !removed || views.some(({ id }) => id === view.id)
94
+ ? views
95
+ : [...views.slice(0, index), removed, ...views.slice(index)]);
96
+ undoDefault?.();
97
+ throw error;
98
+ }
99
+ // Saved only once the view is gone, so a failed delete has no reset
100
+ // to take back.
101
+ if (undoDefault)
102
+ await onSetDefault?.("initial");
103
+ }),
104
+ // Moves the view right away, and moves it back if the save fails. A drop
105
+ // while another reorder saves is skipped.
106
+ onReorder: onReorder &&
107
+ (async (view, target) => {
108
+ if (isReorderingNow.current)
109
+ return;
110
+ const views = savedViews ?? [];
111
+ const from = views.indexOf(view);
112
+ const moved = moveView(views, view, target);
113
+ const to = moved.indexOf(view);
114
+ const after = moved[to - 1] ?? null;
115
+ if (from === -1 || from === to)
116
+ return;
117
+ // The position is saved by the view it follows, which needs an id.
118
+ if (after && after.id === undefined)
119
+ return;
120
+ isReorderingNow.current = true;
121
+ setIsReordering(true);
122
+ const previousOrder = views.map(({ id }) => id);
123
+ setSavedViews((current) => current && moveView(current, view, target));
124
+ try {
125
+ await onReorder(view, after);
126
+ }
127
+ catch (error) {
128
+ setSavedViews((current) => current && restoreOrder(current, previousOrder));
129
+ throw error;
130
+ }
131
+ finally {
132
+ isReorderingNow.current = false;
133
+ setIsReordering(false);
134
+ }
135
+ }),
136
+ onSetDefault: onSetDefault &&
137
+ (async (id) => {
138
+ const undo = changeDefault(id);
139
+ try {
140
+ await onSetDefault(id);
141
+ }
142
+ catch (error) {
143
+ undo();
144
+ throw error;
145
+ }
146
+ }),
147
+ // Shows the change right away. If the save fails, puts back the newest
148
+ // update still saving, or else the last saved version.
149
+ onUpdate: onUpdate &&
150
+ (async (view) => {
151
+ const order = ++latestUpdate.current;
152
+ const tracked = trackUpdates(view);
153
+ startSaving(tracked, view);
154
+ showUpdate(view);
155
+ try {
156
+ const updated = await onUpdate(view);
157
+ const saved = updated && withoutSearch(updated);
158
+ stopSaving(tracked, view);
159
+ confirmIfNewest(tracked, saved ?? view, order);
160
+ if (saved)
161
+ replaceView(view, saved);
162
+ return saved;
163
+ }
164
+ catch (error) {
165
+ stopSaving(tracked, view);
166
+ replaceView(view, viewToRestore(tracked));
167
+ throw error;
168
+ }
169
+ }),
170
+ savedViews,
171
+ };
172
+ }
173
+ function moveView(views, view, { dropPosition, view: target }) {
174
+ const rest = views.filter((existing) => existing !== view);
175
+ const targetIndex = rest.indexOf(target);
176
+ if (targetIndex === -1)
177
+ return views;
178
+ const to = dropPosition === "after" ? targetIndex + 1 : targetIndex;
179
+ return [...rest.slice(0, to), view, ...rest.slice(to)];
180
+ }
181
+ // Matched by id, so views updated or deleted since keep those changes. Views
182
+ // created since stay at the end.
183
+ function restoreOrder(views, order) {
184
+ const indexOf = (view) => {
185
+ const index = order.indexOf(view.id);
186
+ return index === -1 ? order.length : index;
187
+ };
188
+ return [...views].sort((a, b) => indexOf(a) - indexOf(b));
189
+ }
190
+
191
+ export { useSavedViewsState };
192
+ //# sourceMappingURL=useSavedViewsState.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useSavedViewsState.js","sources":["../../../src/components/DataTable/useSavedViewsState.ts"],"sourcesContent":["import { useRef, useState } from \"react\"\n\nimport { type SavedView, withoutSearch } from \"./savedViews\"\n\ninterface SavedViewsStateOptions {\n initialDefaultViewId: NonNullable<SavedView[\"id\"]>\n initialSavedViews: SavedView[] | undefined\n onCreate?: (\n savedView: Omit<SavedView, \"id\">\n ) => Promise<SavedView> | SavedView\n onDelete?: (savedView: SavedView) => Promise<void> | void\n onReorder?: (\n savedView: SavedView,\n after: SavedView | null\n ) => Promise<void> | void\n onSetDefault?: (id: NonNullable<SavedView[\"id\"]>) => Promise<void> | void\n onUpdate?: (savedView: SavedView) => Promise<SavedView> | SavedView\n}\n\ninterface ViewUpdates {\n confirmed: SavedView\n confirmedOrder: number\n saving: SavedView[]\n}\n\nfunction startSaving(updates: ViewUpdates, view: SavedView) {\n updates.saving.push(view)\n}\n\nfunction stopSaving(updates: ViewUpdates, view: SavedView) {\n updates.saving = updates.saving.filter((pending) => pending !== view)\n}\n\n// A slower save of an older update doesn't replace a newer one.\nfunction confirmIfNewest(\n updates: ViewUpdates,\n saved: SavedView,\n order: number\n) {\n if (order <= updates.confirmedOrder) return\n updates.confirmed = saved\n updates.confirmedOrder = order\n}\n\n// The newest update still saving, or else the last saved version.\nfunction viewToRestore(updates: ViewUpdates) {\n return updates.saving.at(-1) ?? updates.confirmed\n}\n\n/**\n * Keeps the saved views and default view id after mount. Each callback is\n * wrapped to apply its change here, and stays undefined when the consumer's is,\n * since that hides the matching action. Updates, deletes, and default changes\n * show right away and are undone if the callback rejects, unless a newer\n * change has replaced them. Reorders save one at a time, so a failed one puts\n * back the order from before it.\n */\nexport function useSavedViewsState({\n initialDefaultViewId,\n initialSavedViews,\n onCreate,\n onDelete,\n onReorder,\n onSetDefault,\n onUpdate,\n}: SavedViewsStateOptions) {\n const [savedViews, setSavedViews] = useState(() =>\n initialSavedViews?.map(withoutSearch)\n )\n const [defaultViewId, setDefaultViewId] = useState(initialDefaultViewId)\n const latestDefaultChange = useRef(0)\n const latestUpdate = useRef(0)\n const updates = useRef(new Map<SavedView[\"id\"], ViewUpdates>())\n const [isReordering, setIsReordering] = useState(false)\n // So a second drop before a render is skipped too.\n const isReorderingNow = useRef(false)\n\n // Only swaps out `current` if it's still there, so a slow save doesn't\n // overwrite a newer change to the same view.\n const replaceView = (current: SavedView, next: SavedView) =>\n setSavedViews((views) =>\n views?.map((view) => (view === current ? next : view))\n )\n\n // Starts from the view as it was last saved, to restore if every update fails.\n const trackUpdates = (view: SavedView) => {\n let tracked = updates.current.get(view.id)\n if (!tracked) {\n const original = savedViews?.find(({ id }) => id === view.id)\n tracked = { confirmed: original ?? view, confirmedOrder: 0, saving: [] }\n updates.current.set(view.id, tracked)\n }\n return tracked\n }\n\n const showUpdate = (view: SavedView) =>\n setSavedViews((views) =>\n views?.map((current) => (current.id === view.id ? view : current))\n )\n\n // Returns an undo that does nothing once a newer default has been set.\n const changeDefault = (id: NonNullable<SavedView[\"id\"]>) => {\n const change = ++latestDefaultChange.current\n let previous = id\n setDefaultViewId((current) => {\n previous = current\n return id\n })\n // Read in an updater, since a callback that rejects right away runs this\n // before the change above has been applied.\n return () => {\n if (latestDefaultChange.current === change)\n setDefaultViewId(() => previous)\n }\n }\n\n return {\n defaultViewId,\n isReordering,\n onCreate:\n onCreate &&\n (async (view: Omit<SavedView, \"id\">) => {\n const created = await onCreate(view)\n const saved = created && withoutSearch(created)\n // Tolerates a consumer that returns nothing, leaving the list as is.\n if (saved) setSavedViews((views = []) => [...views, saved])\n return saved\n }),\n onDelete:\n onDelete &&\n (async (view: SavedView) => {\n let index = -1\n let removed: SavedView | undefined\n setSavedViews((views) => {\n index = views?.findIndex(({ id }) => id === view.id) ?? -1\n removed = views?.[index]\n return views?.filter(({ id }) => id !== view.id)\n })\n const undoDefault =\n view.id === defaultViewId ? changeDefault(\"initial\") : undefined\n try {\n await onDelete(view)\n } catch (error) {\n setSavedViews((views) =>\n !views || !removed || views.some(({ id }) => id === view.id)\n ? views\n : [...views.slice(0, index), removed, ...views.slice(index)]\n )\n undoDefault?.()\n throw error\n }\n // Saved only once the view is gone, so a failed delete has no reset\n // to take back.\n if (undoDefault) await onSetDefault?.(\"initial\")\n }),\n // Moves the view right away, and moves it back if the save fails. A drop\n // while another reorder saves is skipped.\n onReorder:\n onReorder &&\n (async (view: SavedView, target: ReorderTarget) => {\n if (isReorderingNow.current) return\n const views = savedViews ?? []\n const from = views.indexOf(view)\n const moved = moveView(views, view, target)\n const to = moved.indexOf(view)\n const after = moved[to - 1] ?? null\n if (from === -1 || from === to) return\n // The position is saved by the view it follows, which needs an id.\n if (after && after.id === undefined) return\n\n isReorderingNow.current = true\n setIsReordering(true)\n const previousOrder = views.map(({ id }) => id)\n setSavedViews((current) => current && moveView(current, view, target))\n try {\n await onReorder(view, after)\n } catch (error) {\n setSavedViews(\n (current) => current && restoreOrder(current, previousOrder)\n )\n throw error\n } finally {\n isReorderingNow.current = false\n setIsReordering(false)\n }\n }),\n onSetDefault:\n onSetDefault &&\n (async (id: NonNullable<SavedView[\"id\"]>) => {\n const undo = changeDefault(id)\n try {\n await onSetDefault(id)\n } catch (error) {\n undo()\n throw error\n }\n }),\n // Shows the change right away. If the save fails, puts back the newest\n // update still saving, or else the last saved version.\n onUpdate:\n onUpdate &&\n (async (view: SavedView) => {\n const order = ++latestUpdate.current\n const tracked = trackUpdates(view)\n startSaving(tracked, view)\n showUpdate(view)\n try {\n const updated = await onUpdate(view)\n const saved = updated && withoutSearch(updated)\n stopSaving(tracked, view)\n confirmIfNewest(tracked, saved ?? view, order)\n if (saved) replaceView(view, saved)\n return saved\n } catch (error) {\n stopSaving(tracked, view)\n replaceView(view, viewToRestore(tracked))\n throw error\n }\n }),\n savedViews,\n }\n}\n\n/** Where a view was dropped, as React Aria reports it. */\nexport interface ReorderTarget {\n dropPosition: \"after\" | \"before\"\n view: SavedView\n}\n\nfunction moveView(\n views: SavedView[],\n view: SavedView,\n { dropPosition, view: target }: ReorderTarget\n) {\n const rest = views.filter((existing) => existing !== view)\n const targetIndex = rest.indexOf(target)\n if (targetIndex === -1) return views\n const to = dropPosition === \"after\" ? targetIndex + 1 : targetIndex\n return [...rest.slice(0, to), view, ...rest.slice(to)]\n}\n\n// Matched by id, so views updated or deleted since keep those changes. Views\n// created since stay at the end.\nfunction restoreOrder(views: SavedView[], order: SavedView[\"id\"][]) {\n const indexOf = (view: SavedView) => {\n const index = order.indexOf(view.id)\n return index === -1 ? order.length : index\n }\n return [...views].sort((a, b) => indexOf(a) - indexOf(b))\n}\n"],"names":[],"mappings":"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"}