@mvriu5/payload-ai 1.2.0 → 1.3.2

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 (51) hide show
  1. package/README.md +42 -0
  2. package/dist/components/Icons.d.ts +0 -8
  3. package/dist/components/Icons.js +4 -216
  4. package/dist/components/{ActionToast.d.ts → action-toast/ActionToast.d.ts} +1 -2
  5. package/dist/components/{ActionToast.js → action-toast/ActionToast.js} +25 -34
  6. package/dist/components/{ActionToast.module.css → action-toast/ActionToast.module.css} +0 -79
  7. package/dist/components/ai-input/AIInput.js +433 -0
  8. package/dist/components/{AIInput.module.css → ai-input/AIInput.module.css} +111 -43
  9. package/dist/components/ai-input/badge.d.ts +14 -0
  10. package/dist/components/ai-input/badge.js +85 -0
  11. package/dist/components/{AuditLogList.d.ts → audit-log-list/AuditLogList.d.ts} +4 -8
  12. package/dist/components/{AuditLogList.js → audit-log-list/AuditLogList.js} +49 -21
  13. package/dist/components/{AuditLogList.module.css → audit-log-list/AuditLogList.module.css} +11 -65
  14. package/dist/components/dashboard/Dashboard.d.ts +2 -0
  15. package/dist/components/dashboard/Dashboard.js +15 -0
  16. package/dist/components/dashboard/Dashboard.module.css +13 -0
  17. package/dist/components/{DiffDialog.d.ts → diff-dialog/DiffDialog.d.ts} +2 -2
  18. package/dist/components/{DiffDialog.js → diff-dialog/DiffDialog.js} +200 -189
  19. package/dist/components/{DiffDialog.module.css → diff-dialog/DiffDialog.module.css} +17 -35
  20. package/dist/components/hooks/useAIChatStream.d.ts +39 -0
  21. package/dist/components/hooks/useAIChatStream.js +217 -0
  22. package/dist/components/hooks/useAISettings.js +26 -25
  23. package/dist/components/hooks/useAuditLog.d.ts +11 -0
  24. package/dist/components/hooks/useAuditLog.js +41 -0
  25. package/dist/components/hooks/useDocumentMentionSuggestions.d.ts +1 -1
  26. package/dist/components/hooks/useDocumentMentionSuggestions.js +31 -27
  27. package/dist/components/hooks/useMentions.d.ts +58 -0
  28. package/dist/components/hooks/useMentions.js +276 -0
  29. package/dist/components/hooks/usePluginConfig.d.ts +52 -0
  30. package/dist/components/hooks/usePluginConfig.js +20 -0
  31. package/dist/components/{MentionPopover.d.ts → mention-popover/MentionPopover.d.ts} +2 -4
  32. package/dist/components/{MentionPopover.js → mention-popover/MentionPopover.js} +1 -8
  33. package/dist/components/{MentionPopover.module.css → mention-popover/MentionPopover.module.css} +1 -1
  34. package/dist/exports/client.d.ts +2 -2
  35. package/dist/exports/client.js +2 -2
  36. package/dist/handlers/applyActionHandler.js +27 -7
  37. package/dist/handlers/chatHandler.js +302 -58
  38. package/dist/handlers/mediaUploadHandler.d.ts +7 -0
  39. package/dist/handlers/mediaUploadHandler.js +99 -0
  40. package/dist/handlers/mentionSuggestionHandler.js +16 -14
  41. package/dist/handlers/proposalDiffHandler.js +41 -29
  42. package/dist/index.d.ts +6 -0
  43. package/dist/index.js +39 -7
  44. package/dist/payload/collectionPermissions.js +3 -1
  45. package/dist/payload/normalizeData.d.ts +0 -6
  46. package/dist/payload/normalizeData.js +25 -13
  47. package/dist/payload/proposalData.js +4 -1
  48. package/dist/payload/schemaContext.js +98 -43
  49. package/package.json +6 -6
  50. package/dist/components/AIInput.js +0 -896
  51. /package/dist/components/{AIInput.d.ts → ai-input/AIInput.d.ts} +0 -0
package/README.md CHANGED
@@ -54,6 +54,10 @@ import type { PayloadAiPluginOptions } from "@mvriu5/payload-ai";
54
54
  const options: PayloadAiPluginOptions = {
55
55
  allowUserApiKeys: false,
56
56
  collections: {
57
+ media: {
58
+ read: true,
59
+ update: true,
60
+ },
57
61
  posts: {
58
62
  read: true,
59
63
  create: true,
@@ -62,6 +66,12 @@ const options: PayloadAiPluginOptions = {
62
66
  },
63
67
  users: true,
64
68
  },
69
+ media: {
70
+ enabled: true,
71
+ collectionSlug: "media",
72
+ acceptedMimeTypes: ["image/*"],
73
+ maxFileSize: 10 * 1024 * 1024,
74
+ },
65
75
  models: {
66
76
  defaults: {
67
77
  openai: "gpt-4.1-mini",
@@ -124,6 +134,38 @@ payloadAiPlugin({
124
134
 
125
135
  `read` controls schema/context access, document search, and mentions. `create`, `update`, and `delete` control AI action proposals and server-side apply permissions.
126
136
 
137
+ ### `media`
138
+
139
+ Enables media uploads from the AI assistant. Uploaded files are created through the configured Payload upload collection and then passed to the chat endpoint as media attachments.
140
+
141
+ ```ts
142
+ payloadAiPlugin({
143
+ collections: {
144
+ media: {
145
+ read: true,
146
+ update: true,
147
+ },
148
+ posts: true,
149
+ },
150
+ media: {
151
+ enabled: true,
152
+ collectionSlug: "media",
153
+ acceptedMimeTypes: ["image/*"],
154
+ maxFileSize: 10 * 1024 * 1024,
155
+ },
156
+ })
157
+ ```
158
+
159
+ `collectionSlug` defaults to `"media"`. The target collection must be configured with Payload `upload` support.
160
+
161
+ `acceptedMimeTypes` accepts exact MIME types such as `"image/png"` and wildcard groups such as `"image/*"`. If omitted, all file types accepted by the upload collection can be sent to the endpoint.
162
+
163
+ `maxFileSize` is checked before creating the upload document. The value is in bytes.
164
+
165
+ If you want the AI to use uploaded files in other documents, enable `read` on the media collection so the chat endpoint can validate and inspect the uploaded media document. If the media collection has editable fields such as `alt`, `caption`, or `credit` and you want the AI to fill them, also enable `update` for that collection.
166
+
167
+ Upload references in AI proposals are restricted to the uploaded attachments for the current request. This prevents the model from inventing arbitrary media IDs for upload fields.
168
+
127
169
  ### `models`
128
170
 
129
171
  Overrides the model list shown in the admin UI and the default model per provider.
@@ -4,11 +4,3 @@ export declare function OpenaiIcon(props: SVGProps<SVGSVGElement>): import("reac
4
4
  export declare function ClaudeIcon(props: SVGProps<SVGSVGElement>): import("react").JSX.Element;
5
5
  export declare function GoogleGeminiIcon(props: SVGProps<SVGSVGElement>): import("react").JSX.Element;
6
6
  export declare function OpenrouterIcon(props: SVGProps<SVGSVGElement>): import("react").JSX.Element;
7
- export declare function FileDiff(props: SVGProps<SVGSVGElement>): import("react").JSX.Element;
8
- export declare function Send(props: SVGProps<SVGSVGElement>): import("react").JSX.Element;
9
- export declare function Apply(props: SVGProps<SVGSVGElement>): import("react").JSX.Element;
10
- export declare function Reject(props: SVGProps<SVGSVGElement>): import("react").JSX.Element;
11
- export declare function Collection(props: SVGProps<SVGSVGElement>): import("react").JSX.Element;
12
- export declare function Document(props: SVGProps<SVGSVGElement>): import("react").JSX.Element;
13
- export declare function Global(props: SVGProps<SVGSVGElement>): import("react").JSX.Element;
14
- export declare function Block(props: SVGProps<SVGSVGElement>): import("react").JSX.Element;
@@ -257,232 +257,20 @@ export function OpenrouterIcon(props) {
257
257
  clipPath: "url(#clip0_205_3)",
258
258
  children: [
259
259
  /*#__PURE__*/ _jsx("path", {
260
- d: "M3 248.945C18 248.945 76 236 106 219C136 202 136 202 198 158C276.497 102.293 332 120.945 423 120.945",
260
+ d: "M3 248.95C18 248.95 76 236 106 219C136 202 136 202 198 158C276.5 102.29 332 120.95 423 120.95",
261
261
  strokeWidth: "90"
262
262
  }),
263
263
  /*#__PURE__*/ _jsx("path", {
264
- d: "M511 121.5L357.25 210.268L357.25 32.7324L511 121.5Z"
264
+ d: "M511 121.5L357.25 210.27L357.25 32.73L511 121.5Z"
265
265
  }),
266
266
  /*#__PURE__*/ _jsx("path", {
267
- d: "M0 249C15 249 73 261.945 103 278.945C133 295.945 133 295.945 195 339.945C273.497 395.652 329 377 420 377",
267
+ d: "M0 249C15 249 73 261.95 103 278.95C133 295.95 133 295.95 195 339.95C273.5 395.65 329 377 420 377",
268
268
  strokeWidth: "90"
269
269
  }),
270
270
  /*#__PURE__*/ _jsx("path", {
271
- d: "M508 376.445L354.25 287.678L354.25 465.213L508 376.445Z"
271
+ d: "M508 376.45L354.25 287.68L354.25 465.21L508 376.45Z"
272
272
  })
273
273
  ]
274
274
  })
275
275
  });
276
276
  }
277
- export function FileDiff(props) {
278
- return /*#__PURE__*/ _jsxs("svg", {
279
- xmlns: "http://www.w3.org/2000/svg",
280
- viewBox: "0 0 24 24",
281
- fill: "none",
282
- stroke: "currentColor",
283
- strokeWidth: 2,
284
- strokeLinecap: "round",
285
- strokeLinejoin: "round",
286
- ...props,
287
- children: [
288
- /*#__PURE__*/ _jsx("path", {
289
- stroke: "none",
290
- d: "M0 0h24v24H0z",
291
- fill: "none"
292
- }),
293
- /*#__PURE__*/ _jsx("path", {
294
- d: "M14 3v4a1 1 0 0 0 1 1h4"
295
- }),
296
- /*#__PURE__*/ _jsx("path", {
297
- d: "M17 21h-10a2 2 0 0 1 -2 -2v-14a2 2 0 0 1 2 -2h7l5 5v11a2 2 0 0 1 -2 2"
298
- }),
299
- /*#__PURE__*/ _jsx("path", {
300
- d: "M12 10l0 4"
301
- }),
302
- /*#__PURE__*/ _jsx("path", {
303
- d: "M10 12l4 0"
304
- }),
305
- /*#__PURE__*/ _jsx("path", {
306
- d: "M10 17l4 0"
307
- })
308
- ]
309
- });
310
- }
311
- export function Send(props) {
312
- return /*#__PURE__*/ _jsxs("svg", {
313
- xmlns: "http://www.w3.org/2000/svg",
314
- viewBox: "0 0 24 24",
315
- fill: "none",
316
- stroke: "currentColor",
317
- strokeWidth: 2,
318
- strokeLinecap: "round",
319
- strokeLinejoin: "round",
320
- ...props,
321
- children: [
322
- /*#__PURE__*/ _jsx("path", {
323
- stroke: "none",
324
- d: "M0 0h24v24H0z",
325
- fill: "none"
326
- }),
327
- /*#__PURE__*/ _jsx("path", {
328
- d: "M10 14l11 -11"
329
- }),
330
- /*#__PURE__*/ _jsx("path", {
331
- d: "M21 3l-6.5 18a.55 .55 0 0 1 -1 0l-3.5 -7l-7 -3.5a.55 .55 0 0 1 0 -1l18 -6.5"
332
- })
333
- ]
334
- });
335
- }
336
- export function Apply(props) {
337
- return /*#__PURE__*/ _jsxs("svg", {
338
- xmlns: "http://www.w3.org/2000/svg",
339
- viewBox: "0 0 24 24",
340
- fill: "none",
341
- stroke: "currentColor",
342
- strokeWidth: 2,
343
- strokeLinecap: "round",
344
- strokeLinejoin: "round",
345
- ...props,
346
- children: [
347
- /*#__PURE__*/ _jsx("path", {
348
- stroke: "none",
349
- d: "M0 0h24v24H0z",
350
- fill: "none"
351
- }),
352
- /*#__PURE__*/ _jsx("path", {
353
- d: "M5 12l5 5l10 -10"
354
- })
355
- ]
356
- });
357
- }
358
- export function Reject(props) {
359
- return /*#__PURE__*/ _jsxs("svg", {
360
- xmlns: "http://www.w3.org/2000/svg",
361
- viewBox: "0 0 24 24",
362
- fill: "none",
363
- stroke: "currentColor",
364
- strokeWidth: 2,
365
- strokeLinecap: "round",
366
- strokeLinejoin: "round",
367
- ...props,
368
- children: [
369
- /*#__PURE__*/ _jsx("path", {
370
- stroke: "none",
371
- d: "M0 0h24v24H0z",
372
- fill: "none"
373
- }),
374
- /*#__PURE__*/ _jsx("path", {
375
- d: "M18 6l-12 12"
376
- }),
377
- /*#__PURE__*/ _jsx("path", {
378
- d: "M6 6l12 12"
379
- })
380
- ]
381
- });
382
- }
383
- export function Collection(props) {
384
- return /*#__PURE__*/ _jsxs("svg", {
385
- xmlns: "http://www.w3.org/2000/svg",
386
- viewBox: "0 0 24 24",
387
- fill: "none",
388
- stroke: "currentColor",
389
- strokeWidth: 2,
390
- strokeLinecap: "round",
391
- strokeLinejoin: "round",
392
- ...props,
393
- children: [
394
- /*#__PURE__*/ _jsx("path", {
395
- stroke: "none",
396
- d: "M0 0h24v24H0z",
397
- fill: "none"
398
- }),
399
- /*#__PURE__*/ _jsx("path", {
400
- d: "M5 4h4l3 3h7a2 2 0 0 1 2 2v8a2 2 0 0 1 -2 2h-14a2 2 0 0 1 -2 -2v-11a2 2 0 0 1 2 -2"
401
- })
402
- ]
403
- });
404
- }
405
- export function Document(props) {
406
- return /*#__PURE__*/ _jsxs("svg", {
407
- xmlns: "http://www.w3.org/2000/svg",
408
- viewBox: "0 0 24 24",
409
- fill: "none",
410
- stroke: "currentColor",
411
- strokeWidth: 2,
412
- strokeLinecap: "round",
413
- strokeLinejoin: "round",
414
- ...props,
415
- children: [
416
- /*#__PURE__*/ _jsx("path", {
417
- stroke: "none",
418
- d: "M0 0h24v24H0z",
419
- fill: "none"
420
- }),
421
- /*#__PURE__*/ _jsx("path", {
422
- d: "M14 3v4a1 1 0 0 0 1 1h4"
423
- }),
424
- /*#__PURE__*/ _jsx("path", {
425
- d: "M17 21h-10a2 2 0 0 1 -2 -2v-14a2 2 0 0 1 2 -2h7l5 5v11a2 2 0 0 1 -2 2"
426
- })
427
- ]
428
- });
429
- }
430
- export function Global(props) {
431
- return /*#__PURE__*/ _jsxs("svg", {
432
- xmlns: "http://www.w3.org/2000/svg",
433
- viewBox: "0 0 24 24",
434
- fill: "none",
435
- stroke: "currentColor",
436
- strokeWidth: 2,
437
- strokeLinecap: "round",
438
- strokeLinejoin: "round",
439
- ...props,
440
- children: [
441
- /*#__PURE__*/ _jsx("path", {
442
- stroke: "none",
443
- d: "M0 0h24v24H0z",
444
- fill: "none"
445
- }),
446
- /*#__PURE__*/ _jsx("path", {
447
- d: "M3 12a9 9 0 1 0 18 0a9 9 0 0 0 -18 0"
448
- }),
449
- /*#__PURE__*/ _jsx("path", {
450
- d: "M3.6 9h16.8"
451
- }),
452
- /*#__PURE__*/ _jsx("path", {
453
- d: "M3.6 15h16.8"
454
- }),
455
- /*#__PURE__*/ _jsx("path", {
456
- d: "M11.5 3a17 17 0 0 0 0 18"
457
- }),
458
- /*#__PURE__*/ _jsx("path", {
459
- d: "M12.5 3a17 17 0 0 1 0 18"
460
- })
461
- ]
462
- });
463
- }
464
- export function Block(props) {
465
- return /*#__PURE__*/ _jsxs("svg", {
466
- xmlns: "http://www.w3.org/2000/svg",
467
- viewBox: "0 0 24 24",
468
- fill: "none",
469
- stroke: "currentColor",
470
- strokeWidth: 2,
471
- strokeLinecap: "round",
472
- strokeLinejoin: "round",
473
- ...props,
474
- children: [
475
- /*#__PURE__*/ _jsx("path", {
476
- stroke: "none",
477
- d: "M0 0h24v24H0z",
478
- fill: "none"
479
- }),
480
- /*#__PURE__*/ _jsx("path", {
481
- d: "M14 4a1 1 0 0 1 1 -1h5a1 1 0 0 1 1 1v5a1 1 0 0 1 -1 1h-5a1 1 0 0 1 -1 -1l0 -5"
482
- }),
483
- /*#__PURE__*/ _jsx("path", {
484
- d: "M3 14h12a2 2 0 0 1 2 2v3a2 2 0 0 1 -2 2h-10a2 2 0 0 1 -2 -2v-10a2 2 0 0 1 2 -2h3a2 2 0 0 1 2 2v12"
485
- })
486
- ]
487
- });
488
- }
@@ -11,7 +11,6 @@ export type ActionProposal = {
11
11
  };
12
12
  type ActionToastProps = {
13
13
  apiRoute: string;
14
- appliedProposalIndexes: number[];
15
14
  description?: string;
16
15
  error?: string;
17
16
  getViewURL?: (proposal: ActionProposal) => string | null;
@@ -27,5 +26,5 @@ type ActionToastProps = {
27
26
  totalTokens?: number;
28
27
  } | null;
29
28
  };
30
- export declare const ActionToast: ({ apiRoute, appliedProposalIndexes, description, error, getViewURL, isApplying, onDismiss, onDismissError, onApply, prompt, proposals, tokenUsage, }: ActionToastProps) => import("react").JSX.Element | null;
29
+ export declare const ActionToast: ({ apiRoute, description, error, getViewURL, isApplying, onDismiss, onDismissError, onApply, prompt, proposals, tokenUsage, }: ActionToastProps) => import("react").JSX.Element | null;
31
30
  export {};
@@ -1,10 +1,10 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
- import styles from "./ActionToast.module.css";
3
- import { redactSensitiveData } from "../ai/sensitiveData.js";
2
+ import { Button, CheckIcon, SwapIcon } from "@payloadcms/ui";
4
3
  import { formatAdminURL } from "payload/shared";
5
4
  import { useState } from "react";
6
- import { DiffDialog } from "./DiffDialog.js";
7
- import { Apply, FileDiff, Reject } from "./Icons.js";
5
+ import { redactSensitiveData } from "../../ai/sensitiveData.js";
6
+ import { DiffDialog } from "../diff-dialog/DiffDialog.js";
7
+ import styles from "./ActionToast.module.css";
8
8
  const maxDescriptionLength = 220;
9
9
  const getDescriptionPreview = (description)=>{
10
10
  if (description.length <= maxDescriptionLength) return description;
@@ -20,7 +20,7 @@ const getSafeProposalDetails = (proposal)=>{
20
20
  }
21
21
  return redactedProposal;
22
22
  };
23
- export const ActionToast = ({ apiRoute, appliedProposalIndexes, description, error, getViewURL, isApplying, onDismiss, onDismissError, onApply, prompt, proposals, tokenUsage })=>{
23
+ export const ActionToast = ({ apiRoute, description, error, getViewURL, isApplying, onDismiss, onDismissError, onApply, prompt, proposals, tokenUsage })=>{
24
24
  const [activeDiff, setActiveDiff] = useState(null);
25
25
  const [diffError, setDiffError] = useState("");
26
26
  const [loadingDiffIndex, setLoadingDiffIndex] = useState(null);
@@ -117,7 +117,6 @@ export const ActionToast = ({ apiRoute, appliedProposalIndexes, description, err
117
117
  })
118
118
  }),
119
119
  proposals.map((proposal, index)=>{
120
- const isApplied = appliedProposalIndexes.includes(index);
121
120
  const viewURL = getViewURL?.(proposal);
122
121
  return /*#__PURE__*/ _jsxs("div", {
123
122
  className: styles.item,
@@ -176,25 +175,23 @@ export const ActionToast = ({ apiRoute, appliedProposalIndexes, description, err
176
175
  /*#__PURE__*/ _jsxs("div", {
177
176
  className: styles.viewAction,
178
177
  children: [
179
- /*#__PURE__*/ _jsxs("button", {
178
+ /*#__PURE__*/ _jsxs(Button, {
180
179
  "aria-label": `Review proposal: ${proposal.label}`,
181
- className: styles.secondaryButton,
180
+ margin: false,
181
+ buttonStyle: "subtle",
182
182
  disabled: loadingDiffIndex === index,
183
183
  onClick: ()=>void openDiff(proposal, index),
184
- type: "button",
185
184
  children: [
186
- /*#__PURE__*/ _jsx(FileDiff, {
187
- height: 16,
188
- width: 16
189
- }),
185
+ /*#__PURE__*/ _jsx(SwapIcon, {}),
190
186
  loadingDiffIndex === index ? "Loading" : "Review"
191
187
  ]
192
188
  }),
193
- viewURL && /*#__PURE__*/ _jsx("a", {
194
- className: styles.ghostButton,
195
- href: viewURL,
196
- rel: "noreferrer noopener",
197
- target: "_blank",
189
+ viewURL && /*#__PURE__*/ _jsx(Button, {
190
+ el: "anchor",
191
+ buttonStyle: "tab",
192
+ url: viewURL,
193
+ newTab: true,
194
+ margin: false,
198
195
  children: "Go to source"
199
196
  })
200
197
  ]
@@ -202,26 +199,20 @@ export const ActionToast = ({ apiRoute, appliedProposalIndexes, description, err
202
199
  /*#__PURE__*/ _jsxs("div", {
203
200
  className: styles.actions,
204
201
  children: [
205
- onDismiss && /*#__PURE__*/ _jsx("button", {
202
+ onDismiss && /*#__PURE__*/ _jsx(Button, {
203
+ icon: "x",
206
204
  "aria-label": "Dismiss proposals",
207
- className: styles.secondaryButton,
208
- onClick: onDismiss,
209
- type: "button",
210
- children: /*#__PURE__*/ _jsx(Reject, {
211
- height: 16,
212
- width: 16
213
- })
205
+ buttonStyle: "subtle",
206
+ margin: false,
207
+ onClick: onDismiss
214
208
  }),
215
- /*#__PURE__*/ _jsx("button", {
209
+ /*#__PURE__*/ _jsx(Button, {
216
210
  "aria-label": `Apply proposal: ${proposal.label}`,
217
- className: styles.button,
218
- disabled: isApplying || isApplied,
211
+ margin: false,
212
+ buttonStyle: "primary",
213
+ disabled: isApplying,
219
214
  onClick: ()=>onApply(proposal, index),
220
- type: "button",
221
- children: /*#__PURE__*/ _jsx(Apply, {
222
- height: 16,
223
- width: 16
224
- })
215
+ children: /*#__PURE__*/ _jsx(CheckIcon, {})
225
216
  })
226
217
  ]
227
218
  })
@@ -106,79 +106,6 @@
106
106
  gap: 8px;
107
107
  }
108
108
 
109
- .button {
110
- align-items: center;
111
- background: var(--theme-text);
112
- border: 0;
113
- border-radius: 4px;
114
- color: var(--theme-bg);
115
- cursor: pointer;
116
- display: inline-flex;
117
- flex: 0 0 auto;
118
- font: inherit;
119
- gap: 6px;
120
- justify-content: center;
121
- line-height: 24px;
122
- min-height: 24px;
123
- padding: 0 14px;
124
- }
125
-
126
- .secondaryButton {
127
- align-items: center;
128
- background: transparent;
129
- border: 1px solid var(--theme-elevation-150);
130
- border-radius: 4px;
131
- color: var(--theme-text);
132
- cursor: pointer;
133
- display: inline-flex;
134
- flex: 0 0 auto;
135
- font: inherit;
136
- gap: 6px;
137
- justify-content: center;
138
- line-height: 24px;
139
- min-height: 24px;
140
- padding: 0 14px;
141
- text-decoration: none;
142
- }
143
-
144
- .secondaryButton svg {
145
- color: var(--theme-elevation-500);
146
- flex: 0 0 auto;
147
- }
148
-
149
- .button svg {
150
- flex: 0 0 auto;
151
- }
152
-
153
- .ghostButton {
154
- background: transparent;
155
- border: 0;
156
- border-radius: 4px;
157
- color: var(--theme-elevation-600);
158
- cursor: pointer;
159
- flex: 0 0 auto;
160
- font: inherit;
161
- line-height: 24px;
162
- min-height: 24px;
163
- padding: 0 10px;
164
- text-decoration: none;
165
- }
166
-
167
- .ghostButton:hover {
168
- text-decoration: underline;
169
- }
170
-
171
- .button:disabled {
172
- cursor: not-allowed;
173
- opacity: 0.45;
174
- }
175
-
176
- .secondaryButton:disabled,
177
- .ghostButton:disabled {
178
- cursor: not-allowed;
179
- opacity: 0.45;
180
- }
181
-
182
109
  @media (max-width: 768px) {
183
110
  .list {
184
111
  bottom: 16px;
@@ -210,10 +137,4 @@
210
137
  align-items: stretch;
211
138
  flex-direction: column;
212
139
  }
213
-
214
- .button,
215
- .secondaryButton,
216
- .ghostButton {
217
- width: 100%;
218
- }
219
140
  }