@protobase/ui 0.16.0 → 0.17.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 (42) hide show
  1. package/dist/app/current-address.d.ts +5 -1
  2. package/dist/app/current-address.js +2 -1
  3. package/dist/app/displays/record-card.js +28 -16
  4. package/dist/app/embedded-list/embedded-display.js +7 -3
  5. package/dist/app/embedded-list/embedded-list.js +5 -4
  6. package/dist/app/list-page.js +4 -2
  7. package/dist/app/pages/blocks/record-row.js +51 -0
  8. package/dist/app/pages/render-node.js +2 -0
  9. package/dist/app/record-row/record-row-body.js +114 -0
  10. package/dist/app/record-row/record-row.js +93 -0
  11. package/dist/app/record-row/row-window.js +20 -0
  12. package/dist/app/record-row/saved-record-row.js +42 -0
  13. package/dist/app/record-row/use-row-scroll.js +51 -0
  14. package/dist/app/searches/filter-chip-list.js +28 -0
  15. package/dist/app/searches/save-search-button.js +72 -8
  16. package/dist/app/searches/saved-search-rows.js +73 -0
  17. package/dist/app/searches/saved-search-section.js +91 -73
  18. package/dist/app/searches/saved-search.js +7 -3
  19. package/dist/app/searches/saved-searches.js +3 -5
  20. package/dist/app/searches/search-controls.js +13 -2
  21. package/dist/app/searches/search-diff.js +97 -0
  22. package/dist/app/searches/search-name-dialog.js +62 -0
  23. package/dist/app/searches/update-search-dialog.js +196 -0
  24. package/dist/app/searches/use-opened-search.js +15 -0
  25. package/dist/app/searches/use-save-search.js +64 -18
  26. package/dist/app/searches/use-search-row.js +56 -0
  27. package/dist/package.js +1 -1
  28. package/dist/primitives/dialog.js +3 -2
  29. package/dist/primitives/responsive-dialog.d.ts +3 -1
  30. package/dist/primitives/responsive-dialog.js +2 -1
  31. package/dist/shell/assets/app-BSKdnId2.js +66 -0
  32. package/dist/shell/assets/index-D0AzKE47.css +2 -0
  33. package/dist/shell/assets/{index-LBhMBiK4.js → index-DNc-xM_v.js} +1 -1
  34. package/dist/shell/assets/{maplibre-Dy0ZTnFZ.js → maplibre-1qVldvCU.js} +1 -1
  35. package/dist/shell/assets/{record-map-BiWSbqqT.js → record-map-BPHuPMlK.js} +1 -1
  36. package/dist/shell/assets/{records-map-DabYc3ad.js → records-map-BORhj6IH.js} +1 -1
  37. package/dist/shell/assets/{shared-protobase-ui-BURelnPG.js → shared-protobase-ui-CHRI5o6a.js} +1 -1
  38. package/dist/shell/index.html +4 -4
  39. package/dist/shell/protobase.shell.json +1 -1
  40. package/package.json +4 -4
  41. package/dist/shell/assets/app-DJAZP1yB.js +0 -66
  42. package/dist/shell/assets/index-C5pYkUfv.css +0 -2
@@ -0,0 +1,196 @@
1
+ import { Skeleton } from "../../primitives/skeleton.js";
2
+ import { Button } from "../../primitives/button.js";
3
+ import { useClient } from "../../data/api-provider.js";
4
+ import { humanize } from "../../live/naming.js";
5
+ import { defaultOrderBy } from "../list-order.js";
6
+ import { ResponsiveDialog } from "../../primitives/responsive-dialog.js";
7
+ import { countQuery } from "../pages/use-layout-data.js";
8
+ import { EmbeddedList } from "../embedded-list/embedded-list.js";
9
+ import { addedFilter, filterChanges, netChange, removedFilter } from "./search-diff.js";
10
+ import { useFilterChips } from "./use-filter-chips.js";
11
+ import { useMemo } from "react";
12
+ import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
13
+ import { useQuery } from "@tanstack/react-query";
14
+ import { tableDisplay } from "@protobase/schema/internal";
15
+ //#region src/app/searches/update-search-dialog.tsx
16
+ /** How many records each side of the diff shows; its count says how many there are in all. */
17
+ const shownLimit = 12;
18
+ const changeStyle = {
19
+ added: {
20
+ word: "Added",
21
+ className: "text-success-text"
22
+ },
23
+ removed: {
24
+ word: "Removed",
25
+ className: "text-danger-text"
26
+ },
27
+ changed: {
28
+ word: "Changed",
29
+ className: "text-primary-text"
30
+ }
31
+ };
32
+ const FilterChanges = ({ changes }) => /* @__PURE__ */ jsx("ul", {
33
+ "aria-label": "Filter changes",
34
+ className: "divide-y rounded-md border text-[13px]",
35
+ children: changes.map((change) => /* @__PURE__ */ jsxs("li", {
36
+ className: "grid grid-cols-[72px_1fr] gap-3 px-3 py-2",
37
+ children: [/* @__PURE__ */ jsx("span", {
38
+ className: `font-medium ${changeStyle[change.kind].className}`,
39
+ children: changeStyle[change.kind].word
40
+ }), change.kind === "changed" ? /* @__PURE__ */ jsxs("span", { children: [
41
+ /* @__PURE__ */ jsx("span", {
42
+ className: "text-muted-foreground line-through",
43
+ children: change.before
44
+ }),
45
+ " ",
46
+ /* @__PURE__ */ jsx("span", {
47
+ className: "font-medium",
48
+ children: change.label
49
+ })
50
+ ] }) : /* @__PURE__ */ jsx("span", {
51
+ className: change.kind === "removed" ? "text-muted-foreground line-through" : "font-medium",
52
+ children: change.label
53
+ })]
54
+ }, `${change.kind}:${change.label}`))
55
+ });
56
+ /** How many records `filter` finds, none for a filter that can find none (`null`). */
57
+ const useDiffCount = (model, filter) => {
58
+ const query = useQuery({
59
+ ...countQuery(useClient(), model, filter ?? ""),
60
+ enabled: filter !== null
61
+ });
62
+ return filter === null ? 0 : query.data;
63
+ };
64
+ const count = (n, singular, plural) => `${n} ${n === 1 ? singular : plural}`;
65
+ /** One side of the diff: its title and count, and its first records as the list shows them. */
66
+ const RecordsSide = ({ model, view, title, filter, total, plural }) => {
67
+ const cards = view?.list?.displays?.find((display) => display.kind === "cards");
68
+ return /* @__PURE__ */ jsxs("section", {
69
+ "aria-label": title,
70
+ className: "flex flex-col gap-2",
71
+ children: [
72
+ /* @__PURE__ */ jsxs("h3", {
73
+ className: "text-[13px] font-semibold",
74
+ children: [
75
+ title,
76
+ " ",
77
+ /* @__PURE__ */ jsxs("span", {
78
+ className: "font-normal text-muted-foreground",
79
+ children: [
80
+ "(",
81
+ total ?? "…",
82
+ ")"
83
+ ]
84
+ })
85
+ ]
86
+ }),
87
+ total !== void 0 && total > shownLimit && /* @__PURE__ */ jsxs("p", {
88
+ className: "text-xs text-muted-foreground",
89
+ children: [
90
+ "The first ",
91
+ shownLimit,
92
+ " of ",
93
+ total,
94
+ "."
95
+ ]
96
+ }),
97
+ filter === null || total === 0 ? /* @__PURE__ */ jsxs("p", {
98
+ className: "text-[13px] text-muted-foreground",
99
+ children: [
100
+ "No ",
101
+ plural,
102
+ "."
103
+ ]
104
+ }) : /* @__PURE__ */ jsx(EmbeddedList, {
105
+ model,
106
+ view,
107
+ filter,
108
+ sort: defaultOrderBy(model, view),
109
+ limit: shownLimit,
110
+ display: cards?.name ?? tableDisplay,
111
+ row: true,
112
+ link: false,
113
+ empty: `No ${plural}.`
114
+ })
115
+ ]
116
+ });
117
+ };
118
+ /**
119
+ * Asks before a saved search takes the list's filter: what changes in its filters, how many more or fewer records it
120
+ * finds, and the records it would add and drop, each found by the list API (`addedFilter`, `removedFilter`).
121
+ */
122
+ const UpdateSearchDialog = ({ model, view, title, before, after, saveNewLabel, updating, creating, onUpdate, onSaveNew, onCancel }) => {
123
+ const changes = filterChanges(useFilterChips(model, before), useFilterChips(model, after));
124
+ const added = useMemo(() => addedFilter(before, after), [before, after]);
125
+ const removed = useMemo(() => removedFilter(before, after), [before, after]);
126
+ const addedCount = useDiffCount(model, added);
127
+ const removedCount = useDiffCount(model, removed);
128
+ const singular = (view?.names?.singular ?? humanize(model.name)).toLowerCase();
129
+ const plural = (view?.names?.plural ?? humanize(model.name)).toLowerCase();
130
+ const counted = addedCount !== void 0 && removedCount !== void 0;
131
+ return /* @__PURE__ */ jsx(ResponsiveDialog, {
132
+ open: true,
133
+ wide: true,
134
+ title,
135
+ onClose: onCancel,
136
+ actions: /* @__PURE__ */ jsxs(Fragment$1, { children: [
137
+ /* @__PURE__ */ jsx(Button, {
138
+ onClick: onCancel,
139
+ children: "Cancel"
140
+ }),
141
+ /* @__PURE__ */ jsx(Button, {
142
+ loading: creating,
143
+ disabled: updating,
144
+ onClick: onSaveNew,
145
+ children: saveNewLabel
146
+ }),
147
+ /* @__PURE__ */ jsx(Button, {
148
+ variant: "primary",
149
+ loading: updating,
150
+ disabled: creating,
151
+ onClick: onUpdate,
152
+ children: "Update"
153
+ })
154
+ ] }),
155
+ children: /* @__PURE__ */ jsxs("div", {
156
+ className: "flex flex-col gap-4",
157
+ children: [
158
+ changes.length > 0 && /* @__PURE__ */ jsx(FilterChanges, { changes }),
159
+ counted ? /* @__PURE__ */ jsxs("p", {
160
+ className: "text-[13px]",
161
+ children: [/* @__PURE__ */ jsx("span", {
162
+ className: "font-semibold",
163
+ children: netChange(addedCount, removedCount, singular, plural)
164
+ }), /* @__PURE__ */ jsxs("span", {
165
+ className: "text-muted-foreground",
166
+ children: [
167
+ ": ",
168
+ count(addedCount, singular, plural),
169
+ " added, ",
170
+ removedCount,
171
+ " removed"
172
+ ]
173
+ })]
174
+ }) : /* @__PURE__ */ jsx(Skeleton, { className: "h-4 w-48" }),
175
+ /* @__PURE__ */ jsx(RecordsSide, {
176
+ model,
177
+ view,
178
+ title: "Added",
179
+ filter: added,
180
+ total: addedCount,
181
+ plural
182
+ }),
183
+ /* @__PURE__ */ jsx(RecordsSide, {
184
+ model,
185
+ view,
186
+ title: "Removed",
187
+ filter: removed,
188
+ total: removedCount,
189
+ plural
190
+ })
191
+ ]
192
+ })
193
+ });
194
+ };
195
+ //#endregion
196
+ export { UpdateSearchDialog };
@@ -0,0 +1,15 @@
1
+ import { useAppAddress } from "../use-app-address.js";
2
+ //#region src/app/searches/use-opened-search.ts
3
+ /**
4
+ * The saved search the list was opened from, by its key, as the address names it ("View all results" does), and `open`
5
+ * to name another, such as a search just saved.
6
+ */
7
+ const useOpenedSearch = () => {
8
+ const { address, set } = useAppAddress();
9
+ return {
10
+ key: address?.kind === "list" ? address.savedSearch : void 0,
11
+ open: (key) => set({ savedSearch: key })
12
+ };
13
+ };
14
+ //#endregion
15
+ export { useOpenedSearch };
@@ -1,10 +1,12 @@
1
1
  import { useClient } from "../../data/api-provider.js";
2
2
  import { recordKey } from "../../live/model-helpers.js";
3
+ import { humanize } from "../../live/naming.js";
3
4
  import { useToast } from "../../toasts/toast-provider.js";
4
5
  import { useAdminMeta } from "../meta-gate.js";
5
6
  import { useAppAddress } from "../use-app-address.js";
6
7
  import { can } from "../permissions.js";
7
8
  import { useRefreshResource } from "../pages/use-layout-data.js";
9
+ import { useOpenedSearch } from "./use-opened-search.js";
8
10
  import { useSavedSearches } from "./use-saved-searches.js";
9
11
  import { useMutation } from "@tanstack/react-query";
10
12
  import { encodeKey } from "@protobase/schema/internal";
@@ -12,15 +14,18 @@ import { encodeKey } from "@protobase/schema/internal";
12
14
  const message = (error) => error instanceof Error ? error.message : "Something went wrong";
13
15
  /**
14
16
  * A list page's "Save search" button for its `filter`: `save` for someone who can list, create and delete the saved
15
- * searches, `sign-in` for a visitor their resource asks to sign in (`prompt`), nothing otherwise. A press saves the
16
- * filter as a search named `name`, or takes the saved one off again.
17
+ * searches, `sign-in` for a visitor their resource asks to sign in (`prompt`), nothing otherwise. `saved` while a search
18
+ * has the filter, and `remove` takes it off again; otherwise `saveNew` saves the filter as a search, with the name the
19
+ * user gave (`naming` says how to ask for it) or none. While the list was opened from a saved search (`opened`) whose
20
+ * filter differs, `update` gives that search the list's filter.
17
21
  */
18
- const useSaveSearch = (search, filter, name) => {
22
+ const useSaveSearch = (search, filter) => {
19
23
  const meta = useAdminMeta();
20
24
  const client = useClient();
21
25
  const toast = useToast();
22
26
  const refresh = useRefreshResource();
23
27
  const { href, open } = useAppAddress();
28
+ const opened = useOpenedSearch();
24
29
  const { resource } = search;
25
30
  const model = meta.resources[resource];
26
31
  const of = meta.views[resource]?.searchesOf;
@@ -28,18 +33,20 @@ const useSaveSearch = (search, filter, name) => {
28
33
  const usable = model !== void 0 && of !== void 0 && permissions !== void 0 && can(permissions, "create") && can(permissions, "delete");
29
34
  const prompt = meta.signIn?.[resource]?.signIn;
30
35
  const saved = useSavedSearches(resource, usable);
36
+ const keyOf = (row) => encodeKey(recordKey(model, row));
31
37
  const current = of && saved.data?.find((row) => row[of.filter] === filter);
32
- const plural = meta.views[resource]?.names?.plural ?? "saved searches";
33
- const toggle = useMutation({
34
- mutationFn: async (existing) => {
35
- if (existing) await client.remove(resource, encodeKey(recordKey(model, existing)));
36
- else await client.create(resource, {
37
- [of.filter]: filter,
38
- ...of.name && { [of.name]: name }
39
- });
40
- },
41
- onSuccess: (_, existing) => {
42
- if (!existing) toast.show({
38
+ const edited = current || opened.key === void 0 || !permissions || !can(permissions, "update") ? void 0 : saved.data?.find((row) => keyOf(row) === opened.key);
39
+ const names = meta.views[resource]?.names;
40
+ const plural = names?.plural ?? "saved searches";
41
+ const nameField = of?.name === void 0 ? void 0 : model?.fields[of.name];
42
+ const create = useMutation({
43
+ mutationFn: (name) => client.create(resource, {
44
+ [of.filter]: filter,
45
+ ...of.name && { [of.name]: name }
46
+ }),
47
+ onSuccess: (created) => {
48
+ opened.open(keyOf(created.record));
49
+ toast.show({
43
50
  state: "success",
44
51
  title: "Search saved",
45
52
  action: {
@@ -52,19 +59,58 @@ const useSaveSearch = (search, filter, name) => {
52
59
  }
53
60
  });
54
61
  },
55
- onError: (error, existing) => toast.show({
62
+ onError: (error) => toast.show({
63
+ state: "error",
64
+ title: "Could not save the search",
65
+ description: message(error)
66
+ }),
67
+ onSettled: () => refresh(resource)
68
+ });
69
+ const remove = useMutation({
70
+ mutationFn: (row) => client.remove(resource, keyOf(row)),
71
+ onError: (error) => toast.show({
56
72
  state: "error",
57
- title: existing ? "Could not take the search off" : "Could not save the search",
73
+ title: "Could not take the search off",
58
74
  description: message(error)
59
75
  }),
60
76
  onSettled: () => refresh(resource)
61
77
  });
78
+ const update = useMutation({
79
+ mutationFn: (row) => client.update(resource, keyOf(row), { [of.filter]: filter }, row.etag ?? "*"),
80
+ onSuccess: () => toast.show({
81
+ state: "success",
82
+ title: "Search updated"
83
+ }),
84
+ onError: (error) => toast.show({
85
+ state: "error",
86
+ title: "Could not update the search",
87
+ description: message(error)
88
+ }),
89
+ onSettled: () => refresh(resource)
90
+ });
91
+ const pending = create.isPending || remove.isPending || update.isPending;
62
92
  return {
63
93
  mode: usable ? "save" : prompt ? "sign-in" : void 0,
64
94
  prompt,
65
95
  saved: current !== void 0,
66
- ready: saved.data !== void 0 && !toggle.isPending,
67
- toggle: () => toggle.mutate(current)
96
+ /** The search the list was opened from and differs from: its filter, and its name when it has one. */
97
+ opened: edited && {
98
+ filter: String(edited[of.filter] ?? ""),
99
+ name: of.name && typeof edited[of.name] === "string" && edited[of.name] !== "" ? String(edited[of.name]) : void 0
100
+ },
101
+ /** What one search is called, as the saved searches' view names it. */
102
+ noun: (names?.singular ?? humanize(resource)).toLowerCase(),
103
+ /** How to ask for a new search's name, from its field and view; none when searches have no name. */
104
+ naming: nameField && {
105
+ label: meta.views[resource]?.fields[nameField.name]?.label ?? humanize(nameField.name),
106
+ required: !nameField.nullable
107
+ },
108
+ ready: saved.data !== void 0 && !pending,
109
+ updating: update.isPending,
110
+ creating: create.isPending,
111
+ remove: () => current && remove.mutate(current),
112
+ saveNew: (name, options) => create.mutate(name, options),
113
+ update: (options) => edited && update.mutate(edited, options)
68
114
  };
69
115
  };
70
116
  //#endregion
@@ -0,0 +1,56 @@
1
+ import { useClient } from "../../data/api-provider.js";
2
+ import { humanize } from "../../live/naming.js";
3
+ import { countQuery, useRefreshResource } from "../pages/use-layout-data.js";
4
+ import { isUnseen, unseenFilter } from "./saved-search.js";
5
+ import { chipsText } from "./filter-chip-list.js";
6
+ import { useFilterChips } from "./use-filter-chips.js";
7
+ import { useMutation, useQuery } from "@tanstack/react-query";
8
+ //#region src/app/searches/use-search-row.ts
9
+ /**
10
+ * One saved search as a row of what it finds: its name, if it has one, its filters as chips, its title (the name, or
11
+ * the chips as words), and the `RecordRowBody` of its records: with `unseen` newest first, those new to the user marked
12
+ * "New", saying so when none are, and "View all results", which opens the list from the search and counts as having
13
+ * seen them.
14
+ */
15
+ const useSearchRow = ({ model, of, target, targetView, row, recordKey }) => {
16
+ const client = useClient();
17
+ const refresh = useRefreshResource();
18
+ const filter = String(row[of.filter] ?? "");
19
+ const chips = useFilterChips(target, filter);
20
+ const stored = of.name === void 0 ? void 0 : row[of.name];
21
+ const name = typeof stored === "string" && stored !== "" ? stored : void 0;
22
+ const unseen = of.unseen;
23
+ const markSeen = useMutation({
24
+ mutationFn: (seenAt) => client.update(model.name, recordKey, { [unseen.seenAt]: seenAt }, row.etag ?? "*"),
25
+ onSettled: () => refresh(model.name)
26
+ });
27
+ const newCount = useQuery({
28
+ ...countQuery(client, target, unseen ? unseenFilter(filter, unseen.field, row[unseen.seenAt]) : ""),
29
+ enabled: unseen !== void 0
30
+ });
31
+ const plural = (targetView?.names?.plural ?? humanize(target.name)).toLowerCase();
32
+ const body = {
33
+ model: target,
34
+ view: targetView,
35
+ filter,
36
+ sort: unseen ? `${unseen.field} desc` : void 0,
37
+ limit: of.limit,
38
+ chips: name !== void 0,
39
+ empty: `No ${plural} match.`,
40
+ note: unseen && newCount.data === 0 && `No new ${plural} since you last looked.`,
41
+ isNew: unseen && ((record) => isUnseen(record.record[unseen.field], row[unseen.seenAt])),
42
+ viewAll: {
43
+ label: "View all results",
44
+ savedSearch: recordKey,
45
+ ...unseen && { onOpen: () => markSeen.mutate((/* @__PURE__ */ new Date()).toISOString()) }
46
+ }
47
+ };
48
+ return {
49
+ name,
50
+ chips,
51
+ title: name ?? chipsText(chips),
52
+ body
53
+ };
54
+ };
55
+ //#endregion
56
+ export { useSearchRow };
package/dist/package.js CHANGED
@@ -1,5 +1,5 @@
1
1
  //#region package.json
2
- var version = "0.16.0";
2
+ var version = "0.17.0";
3
3
  var protobase = { "pluginApi": 1 };
4
4
  //#endregion
5
5
  export { protobase, version };
@@ -1,9 +1,10 @@
1
+ import { cn } from "../lib/cn.js";
1
2
  import { useFocusTrap } from "../lib/use-focus-trap.js";
2
3
  import { useRef } from "react";
3
4
  import { jsx, jsxs } from "react/jsx-runtime";
4
5
  //#region src/primitives/dialog.tsx
5
6
  /** A modal with a title, optional body and action buttons. Closes on Escape and on a click outside. */
6
- const Dialog = ({ title, description, onClose, actions, children }) => {
7
+ const Dialog = ({ title, description, onClose, actions, children, wide = false }) => {
7
8
  const panel = useRef(null);
8
9
  useFocusTrap(panel, true, onClose);
9
10
  return /* @__PURE__ */ jsx("div", {
@@ -15,7 +16,7 @@ const Dialog = ({ title, description, onClose, actions, children }) => {
15
16
  role: "dialog",
16
17
  "aria-modal": "true",
17
18
  "aria-label": title,
18
- className: "outline-none max-h-[90vh] w-full max-w-md overflow-y-auto rounded-lg border bg-background p-4 shadow-pop sm:p-5",
19
+ className: cn("outline-none max-h-[90vh] w-full overflow-y-auto rounded-lg border bg-background p-4 shadow-pop sm:p-5", wide ? "max-w-3xl" : "max-w-md"),
19
20
  children: [
20
21
  /* @__PURE__ */ jsx("h2", {
21
22
  className: "text-[15px] font-semibold",
@@ -8,10 +8,12 @@ export type ResponsiveDialogProps = {
8
8
  /** Buttons: right-aligned in the modal, stacked full width at the bottom of the sheet. */
9
9
  actions: ReactNode;
10
10
  children?: ReactNode;
11
+ /** Room for a row of cards or a table in the modal's body. */
12
+ wide?: boolean;
11
13
  };
12
14
  /**
13
15
  * A modal centred on the screen from the `md` breakpoint up, and a sheet rising from the bottom on a phone, switching as
14
16
  * the viewport does. Both close on Escape and on a press outside, and keep focus inside while open.
15
17
  */
16
- export declare const ResponsiveDialog: ({ title, description, open, onClose, actions, children }: ResponsiveDialogProps) => import("react").JSX.Element | null;
18
+ export declare const ResponsiveDialog: ({ title, description, open, onClose, actions, children, wide }: ResponsiveDialogProps) => import("react").JSX.Element | null;
17
19
  //#endregion
@@ -7,7 +7,7 @@ import { jsx, jsxs } from "react/jsx-runtime";
7
7
  * A modal centred on the screen from the `md` breakpoint up, and a sheet rising from the bottom on a phone, switching as
8
8
  * the viewport does. Both close on Escape and on a press outside, and keep focus inside while open.
9
9
  */
10
- const ResponsiveDialog = ({ title, description, open, onClose, actions, children }) => {
10
+ const ResponsiveDialog = ({ title, description, open, onClose, actions, children, wide }) => {
11
11
  const desktop = useIsDesktop();
12
12
  if (!open) return null;
13
13
  if (desktop) return /* @__PURE__ */ jsx(Dialog, {
@@ -15,6 +15,7 @@ const ResponsiveDialog = ({ title, description, open, onClose, actions, children
15
15
  description,
16
16
  onClose,
17
17
  actions,
18
+ wide,
18
19
  children
19
20
  });
20
21
  return /* @__PURE__ */ jsx(Sheet, {