@jhb.software/payload-alt-text-plugin 0.4.2 → 0.4.4

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 (39) hide show
  1. package/dist/components/AltTextField.js +4 -1
  2. package/dist/components/AltTextField.js.map +1 -1
  3. package/dist/components/AltTextHealthWidget.js +85 -77
  4. package/dist/components/AltTextHealthWidget.js.map +1 -1
  5. package/dist/components/BulkGenerateAltTextsButton.js +16 -12
  6. package/dist/components/BulkGenerateAltTextsButton.js.map +1 -1
  7. package/dist/components/GenerateAltTextButton.d.ts +3 -1
  8. package/dist/components/GenerateAltTextButton.js +9 -3
  9. package/dist/components/GenerateAltTextButton.js.map +1 -1
  10. package/dist/components/icons/ArrowRightIcon.d.ts +2 -0
  11. package/dist/components/icons/ArrowRightIcon.js +21 -0
  12. package/dist/components/icons/ArrowRightIcon.js.map +1 -0
  13. package/dist/components/icons/CheckIcon.d.ts +2 -0
  14. package/dist/components/icons/CheckIcon.js +21 -0
  15. package/dist/components/icons/CheckIcon.js.map +1 -0
  16. package/dist/components/icons/ImageIcon.d.ts +2 -0
  17. package/dist/components/icons/ImageIcon.js +21 -0
  18. package/dist/components/icons/ImageIcon.js.map +1 -0
  19. package/dist/components/icons/Lightning.js +8 -4
  20. package/dist/components/icons/Lightning.js.map +1 -1
  21. package/dist/endpoints/bulkGenerateAltTexts.js +4 -0
  22. package/dist/endpoints/bulkGenerateAltTexts.js.map +1 -1
  23. package/dist/endpoints/generateAltText.js +8 -0
  24. package/dist/endpoints/generateAltText.js.map +1 -1
  25. package/dist/fields/altTextField.d.ts +2 -1
  26. package/dist/fields/altTextField.js +4 -1
  27. package/dist/fields/altTextField.js.map +1 -1
  28. package/dist/plugin.js +2 -1
  29. package/dist/plugin.js.map +1 -1
  30. package/dist/resolvers/openAI.js +8 -1
  31. package/dist/resolvers/openAI.js.map +1 -1
  32. package/dist/resolvers/types.d.ts +2 -0
  33. package/dist/resolvers/types.js.map +1 -1
  34. package/dist/translations/de.js +12 -12
  35. package/dist/translations/de.js.map +1 -1
  36. package/dist/translations/en.js +11 -11
  37. package/dist/translations/en.js.map +1 -1
  38. package/dist/translations/translation-schema.json +4 -6
  39. package/package.json +3 -1
@@ -4,6 +4,7 @@ import { FieldLabel, TextareaInput, useDocumentInfo, useField } from '@payloadcm
4
4
  import { GenerateAltTextButton } from './GenerateAltTextButton.js';
5
5
  export const AltTextField = (clientProps)=>{
6
6
  const { field, path } = clientProps;
7
+ const supportedMimeTypes = field.admin?.custom?.supportedMimeTypes;
7
8
  const { setValue, value } = useField({
8
9
  path
9
10
  });
@@ -26,7 +27,9 @@ export const AltTextField = (clientProps)=>{
26
27
  /*#__PURE__*/ _jsx("div", {
27
28
  className: "field-type__wrap",
28
29
  children: /*#__PURE__*/ _jsx(TextareaInput, {
29
- AfterInput: /*#__PURE__*/ _jsx(GenerateAltTextButton, {}),
30
+ AfterInput: /*#__PURE__*/ _jsx(GenerateAltTextButton, {
31
+ supportedMimeTypes: supportedMimeTypes
32
+ }),
30
33
  onChange: (e)=>setValue(e.target.value),
31
34
  path: path,
32
35
  required: required,
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/components/AltTextField.tsx"],"sourcesContent":["'use client'\n\nimport type { TextareaFieldClientProps } from 'payload'\n\nimport { FieldLabel, TextareaInput, useDocumentInfo, useField } from '@payloadcms/ui'\n\nimport { GenerateAltTextButton } from './GenerateAltTextButton.js'\n\nexport const AltTextField = (clientProps: TextareaFieldClientProps) => {\n const { field, path } = clientProps\n\n const { setValue, value } = useField<string>({ path })\n const { id } = useDocumentInfo()\n\n // the field should be optional when the document is created\n // (since the alt text generation can only be used once the document is created and the image uploaded)\n const required = id ? field.required : false\n\n return (\n <div className=\"field-type textarea\" style={{ flex: '1 1 auto' }}>\n <FieldLabel\n htmlFor={`field-${path}`}\n label={field.label}\n localized={field.localized}\n required={required}\n />\n\n <div className=\"field-type__wrap\">\n <TextareaInput\n AfterInput={<GenerateAltTextButton />}\n onChange={(e: React.ChangeEvent<HTMLTextAreaElement>) => setValue(e.target.value)}\n path={path}\n required={required}\n value={value}\n />\n </div>\n </div>\n )\n}\n"],"names":["FieldLabel","TextareaInput","useDocumentInfo","useField","GenerateAltTextButton","AltTextField","clientProps","field","path","setValue","value","id","required","div","className","style","flex","htmlFor","label","localized","AfterInput","onChange","e","target"],"mappings":"AAAA;;AAIA,SAASA,UAAU,EAAEC,aAAa,EAAEC,eAAe,EAAEC,QAAQ,QAAQ,iBAAgB;AAErF,SAASC,qBAAqB,QAAQ,6BAA4B;AAElE,OAAO,MAAMC,eAAe,CAACC;IAC3B,MAAM,EAAEC,KAAK,EAAEC,IAAI,EAAE,GAAGF;IAExB,MAAM,EAAEG,QAAQ,EAAEC,KAAK,EAAE,GAAGP,SAAiB;QAAEK;IAAK;IACpD,MAAM,EAAEG,EAAE,EAAE,GAAGT;IAEf,4DAA4D;IAC5D,uGAAuG;IACvG,MAAMU,WAAWD,KAAKJ,MAAMK,QAAQ,GAAG;IAEvC,qBACE,MAACC;QAAIC,WAAU;QAAsBC,OAAO;YAAEC,MAAM;QAAW;;0BAC7D,KAAChB;gBACCiB,SAAS,CAAC,MAAM,EAAET,MAAM;gBACxBU,OAAOX,MAAMW,KAAK;gBAClBC,WAAWZ,MAAMY,SAAS;gBAC1BP,UAAUA;;0BAGZ,KAACC;gBAAIC,WAAU;0BACb,cAAA,KAACb;oBACCmB,0BAAY,KAAChB;oBACbiB,UAAU,CAACC,IAA8Cb,SAASa,EAAEC,MAAM,CAACb,KAAK;oBAChFF,MAAMA;oBACNI,UAAUA;oBACVF,OAAOA;;;;;AAKjB,EAAC"}
1
+ {"version":3,"sources":["../../src/components/AltTextField.tsx"],"sourcesContent":["'use client'\n\nimport type { TextareaFieldClientProps } from 'payload'\n\nimport { FieldLabel, TextareaInput, useDocumentInfo, useField } from '@payloadcms/ui'\n\nimport { GenerateAltTextButton } from './GenerateAltTextButton.js'\n\nexport const AltTextField = (clientProps: TextareaFieldClientProps) => {\n const { field, path } = clientProps\n\n const supportedMimeTypes = field.admin?.custom?.supportedMimeTypes as string[] | undefined\n\n const { setValue, value } = useField<string>({ path })\n const { id } = useDocumentInfo()\n\n // the field should be optional when the document is created\n // (since the alt text generation can only be used once the document is created and the image uploaded)\n const required = id ? field.required : false\n\n return (\n <div className=\"field-type textarea\" style={{ flex: '1 1 auto' }}>\n <FieldLabel\n htmlFor={`field-${path}`}\n label={field.label}\n localized={field.localized}\n required={required}\n />\n\n <div className=\"field-type__wrap\">\n <TextareaInput\n AfterInput={<GenerateAltTextButton supportedMimeTypes={supportedMimeTypes} />}\n onChange={(e: React.ChangeEvent<HTMLTextAreaElement>) => setValue(e.target.value)}\n path={path}\n required={required}\n value={value}\n />\n </div>\n </div>\n )\n}\n"],"names":["FieldLabel","TextareaInput","useDocumentInfo","useField","GenerateAltTextButton","AltTextField","clientProps","field","path","supportedMimeTypes","admin","custom","setValue","value","id","required","div","className","style","flex","htmlFor","label","localized","AfterInput","onChange","e","target"],"mappings":"AAAA;;AAIA,SAASA,UAAU,EAAEC,aAAa,EAAEC,eAAe,EAAEC,QAAQ,QAAQ,iBAAgB;AAErF,SAASC,qBAAqB,QAAQ,6BAA4B;AAElE,OAAO,MAAMC,eAAe,CAACC;IAC3B,MAAM,EAAEC,KAAK,EAAEC,IAAI,EAAE,GAAGF;IAExB,MAAMG,qBAAqBF,MAAMG,KAAK,EAAEC,QAAQF;IAEhD,MAAM,EAAEG,QAAQ,EAAEC,KAAK,EAAE,GAAGV,SAAiB;QAAEK;IAAK;IACpD,MAAM,EAAEM,EAAE,EAAE,GAAGZ;IAEf,4DAA4D;IAC5D,uGAAuG;IACvG,MAAMa,WAAWD,KAAKP,MAAMQ,QAAQ,GAAG;IAEvC,qBACE,MAACC;QAAIC,WAAU;QAAsBC,OAAO;YAAEC,MAAM;QAAW;;0BAC7D,KAACnB;gBACCoB,SAAS,CAAC,MAAM,EAAEZ,MAAM;gBACxBa,OAAOd,MAAMc,KAAK;gBAClBC,WAAWf,MAAMe,SAAS;gBAC1BP,UAAUA;;0BAGZ,KAACC;gBAAIC,WAAU;0BACb,cAAA,KAAChB;oBACCsB,0BAAY,KAACnB;wBAAsBK,oBAAoBA;;oBACvDe,UAAU,CAACC,IAA8Cb,SAASa,EAAEC,MAAM,CAACb,KAAK;oBAChFL,MAAMA;oBACNO,UAAUA;oBACVF,OAAOA;;;;;AAKjB,EAAC"}
@@ -1,19 +1,12 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
+ import { Pill } from '@payloadcms/ui/elements/Pill';
2
3
  import { getAltTextHealthWidgetData } from '../utilities/altTextHealth.js';
3
4
  import { getAltTextHealthWidgetDisplayState } from '../utilities/altTextHealthWidgetDisplay.js';
4
5
  import { getCollectionLabel } from '../utilities/getCollectionLabel.js';
5
- const badgeStyles = {
6
- healthy: {
7
- background: '#dcfce7',
8
- color: '#15803d'
9
- },
10
- unhealthy: {
11
- background: '#fee2e2',
12
- color: '#991b1b'
13
- }
14
- };
6
+ import { ArrowRightIcon } from './icons/ArrowRightIcon.js';
7
+ import { CheckIcon } from './icons/CheckIcon.js';
8
+ import { ImageIcon } from './icons/ImageIcon.js';
15
9
  export async function AltTextHealthWidget({ req }) {
16
- // Plugin translation keys are not in Payload's built-in key union
17
10
  const t = req.t;
18
11
  const { collections, errors, isLocalized, localeCount, totalDocs } = await getAltTextHealthWidgetData(req);
19
12
  return /*#__PURE__*/ _jsxs("div", {
@@ -32,13 +25,26 @@ export async function AltTextHealthWidget({ req }) {
32
25
  gap: '4px'
33
26
  },
34
27
  children: [
35
- /*#__PURE__*/ _jsx("h3", {
28
+ /*#__PURE__*/ _jsxs("div", {
36
29
  style: {
37
- fontSize: '18px',
38
- fontWeight: 600,
39
- margin: 0
30
+ alignItems: 'center',
31
+ display: 'flex',
32
+ gap: '0.5rem'
40
33
  },
41
- children: t('@jhb.software/payload-alt-text-plugin:altTextHealthWidget')
34
+ children: [
35
+ /*#__PURE__*/ _jsx("div", {
36
+ style: {
37
+ color: 'var(--theme-elevation-500)'
38
+ },
39
+ children: /*#__PURE__*/ _jsx(ImageIcon, {})
40
+ }),
41
+ /*#__PURE__*/ _jsx("h3", {
42
+ style: {
43
+ margin: 0
44
+ },
45
+ children: t('@jhb.software/payload-alt-text-plugin:altTextHealthWidget')
46
+ })
47
+ ]
42
48
  }),
43
49
  /*#__PURE__*/ _jsx("p", {
44
50
  style: {
@@ -80,7 +86,7 @@ export async function AltTextHealthWidget({ req }) {
80
86
  alignItems: 'center',
81
87
  background: 'var(--theme-elevation-50)',
82
88
  border: '1px solid var(--theme-border-color)',
83
- borderRadius: '10px',
89
+ borderRadius: 'var(--style-radius-m)',
84
90
  display: 'flex',
85
91
  gap: '12px',
86
92
  justifyContent: 'space-between',
@@ -117,75 +123,77 @@ export async function AltTextHealthWidget({ req }) {
117
123
  opacity: 0.7
118
124
  },
119
125
  children: [
120
- t('@jhb.software/payload-alt-text-plugin:totalImageCount').replace('{count}', String(collection.totalDocs)),
126
+ /*#__PURE__*/ _jsx("span", {
127
+ style: {
128
+ whiteSpace: 'nowrap'
129
+ },
130
+ children: t('@jhb.software/payload-alt-text-plugin:totalImageCount', {
131
+ count: collection.totalDocs
132
+ })
133
+ }),
121
134
  isLocalized && /*#__PURE__*/ _jsxs(_Fragment, {
122
135
  children: [
123
136
  ' · ',
124
- t('@jhb.software/payload-alt-text-plugin:localeCount').replace('{count}', String(localeCount))
137
+ /*#__PURE__*/ _jsx("span", {
138
+ style: {
139
+ whiteSpace: 'nowrap'
140
+ },
141
+ children: t('@jhb.software/payload-alt-text-plugin:localeCount', {
142
+ count: localeCount
143
+ })
144
+ })
125
145
  ]
126
146
  })
127
147
  ]
128
148
  })
129
149
  ]
130
150
  }),
131
- displayState === 'unhealthy' && collection.invalidDocIds && collection.invalidDocIds.length > 0 ? /*#__PURE__*/ _jsxs("a", {
132
- href: `${req.payload.config.routes.admin}/collections/${collection.collection}?where[id][in]=${collection.invalidDocIds.join(',')}`,
133
- style: {
134
- background: badgeStyles.unhealthy.background,
135
- borderRadius: '999px',
136
- color: badgeStyles.unhealthy.color,
137
- flexShrink: 0,
138
- fontSize: '12px',
139
- fontWeight: 600,
140
- padding: '4px 10px',
141
- textDecoration: 'none',
142
- whiteSpace: 'nowrap'
143
- },
144
- children: [
145
- collection.missingDocs + collection.partialDocs,
146
- ' ',
147
- t('@jhb.software/payload-alt-text-plugin:statusUnhealthy'),
148
- " →"
149
- ]
150
- }) : displayState === 'healthy' ? /*#__PURE__*/ _jsxs("span", {
151
- style: {
152
- background: badgeStyles.healthy.background,
153
- borderRadius: '999px',
154
- color: badgeStyles.healthy.color,
155
- flexShrink: 0,
156
- fontSize: '12px',
157
- fontWeight: 600,
158
- padding: '4px 10px',
159
- whiteSpace: 'nowrap'
160
- },
161
- children: [
162
- t('@jhb.software/payload-alt-text-plugin:statusHealthy'),
163
- " "
164
- ]
165
- }) : displayState === 'unhealthy' ? /*#__PURE__*/ _jsxs("span", {
166
- style: {
167
- background: badgeStyles.unhealthy.background,
168
- borderRadius: '999px',
169
- color: badgeStyles.unhealthy.color,
170
- flexShrink: 0,
171
- fontSize: '12px',
172
- fontWeight: 600,
173
- padding: '4px 10px',
174
- whiteSpace: 'nowrap'
175
- },
176
- children: [
177
- collection.missingDocs + collection.partialDocs,
178
- ' ',
179
- t('@jhb.software/payload-alt-text-plugin:statusUnhealthy')
180
- ]
181
- }) : /*#__PURE__*/ _jsx("span", {
182
- style: {
183
- color: '#92400e',
184
- flexShrink: 0,
185
- fontSize: '12px',
186
- fontWeight: 600,
187
- whiteSpace: 'nowrap'
188
- },
151
+ displayState === 'unhealthy' && collection.invalidDocIds && collection.invalidDocIds.length > 0 ? /*#__PURE__*/ _jsx(Pill, {
152
+ pillStyle: "error",
153
+ size: "small",
154
+ to: `${req.payload.config.routes.admin}/collections/${collection.collection}?where[id][in]=${collection.invalidDocIds.join(',')}`,
155
+ children: /*#__PURE__*/ _jsxs("div", {
156
+ style: {
157
+ alignItems: 'center',
158
+ display: 'flex',
159
+ gap: '0.25rem'
160
+ },
161
+ children: [
162
+ t('@jhb.software/payload-alt-text-plugin:statusUnhealthy', {
163
+ count: collection.missingDocs + collection.partialDocs
164
+ }),
165
+ /*#__PURE__*/ _jsx(ArrowRightIcon, {
166
+ height: "12",
167
+ width: "12"
168
+ })
169
+ ]
170
+ })
171
+ }) : displayState === 'healthy' ? /*#__PURE__*/ _jsx(Pill, {
172
+ pillStyle: "success",
173
+ size: "small",
174
+ children: /*#__PURE__*/ _jsxs("div", {
175
+ style: {
176
+ alignItems: 'center',
177
+ display: 'flex',
178
+ gap: '0.25rem'
179
+ },
180
+ children: [
181
+ t('@jhb.software/payload-alt-text-plugin:statusHealthy'),
182
+ /*#__PURE__*/ _jsx(CheckIcon, {
183
+ height: "12",
184
+ width: "12"
185
+ })
186
+ ]
187
+ })
188
+ }) : displayState === 'unhealthy' ? /*#__PURE__*/ _jsx(Pill, {
189
+ pillStyle: "error",
190
+ size: "small",
191
+ children: t('@jhb.software/payload-alt-text-plugin:statusUnhealthy', {
192
+ count: collection.missingDocs + collection.partialDocs
193
+ })
194
+ }) : /*#__PURE__*/ _jsx(Pill, {
195
+ pillStyle: "warning",
196
+ size: "small",
189
197
  children: t('@jhb.software/payload-alt-text-plugin:collectionCheckFailed')
190
198
  })
191
199
  ]
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/components/AltTextHealthWidget.tsx"],"sourcesContent":["import type { WidgetServerProps } from 'payload'\n\nimport { getAltTextHealthWidgetData } from '../utilities/altTextHealth.js'\nimport { getAltTextHealthWidgetDisplayState } from '../utilities/altTextHealthWidgetDisplay.js'\nimport { getCollectionLabel } from '../utilities/getCollectionLabel.js'\n\nconst badgeStyles = {\n healthy: { background: '#dcfce7', color: '#15803d' },\n unhealthy: { background: '#fee2e2', color: '#991b1b' },\n}\n\nexport async function AltTextHealthWidget({ req }: WidgetServerProps) {\n // Plugin translation keys are not in Payload's built-in key union\n const t = req.t as (key: string) => string\n const { collections, errors, isLocalized, localeCount, totalDocs } =\n await getAltTextHealthWidgetData(req)\n\n return (\n <div\n className=\"card\"\n style={{\n display: 'flex',\n flexDirection: 'column',\n gap: '16px',\n height: '100%',\n }}\n >\n <div style={{ display: 'flex', flexDirection: 'column', gap: '4px' }}>\n <h3 style={{ fontSize: '18px', fontWeight: 600, margin: 0 }}>\n {t('@jhb.software/payload-alt-text-plugin:altTextHealthWidget')}\n </h3>\n <p style={{ color: 'var(--theme-text)', fontSize: '14px', margin: 0, opacity: 0.75 }}>\n {t('@jhb.software/payload-alt-text-plugin:altTextHealthDescription')}\n </p>\n </div>\n\n {totalDocs === 0 && errors.length === 0 && (\n <p style={{ color: 'var(--theme-text)', margin: 0, opacity: 0.75 }}>\n {t('@jhb.software/payload-alt-text-plugin:noImagesFound')}\n </p>\n )}\n\n {errors.length > 0 && (\n <p style={{ color: '#92400e', fontSize: '13px', margin: 0 }}>\n {t('@jhb.software/payload-alt-text-plugin:healthCheckPartialWarning')}\n </p>\n )}\n\n <div style={{ display: 'flex', flexDirection: 'column', gap: '10px' }}>\n {collections.map((collection) => {\n const displayState = getAltTextHealthWidgetDisplayState(collection)\n\n return (\n <div\n key={collection.collection}\n style={{\n alignItems: 'center',\n background: 'var(--theme-elevation-50)',\n border: '1px solid var(--theme-border-color)',\n borderRadius: '10px',\n display: 'flex',\n gap: '12px',\n justifyContent: 'space-between',\n padding: '12px 16px',\n }}\n >\n <div style={{ display: 'flex', flexDirection: 'column', gap: '2px', minWidth: 0 }}>\n <a\n href={`${req.payload.config.routes.admin}/collections/${collection.collection}`}\n style={{\n color: 'var(--theme-text)',\n fontSize: '14px',\n fontWeight: 500,\n textDecoration: 'none',\n }}\n >\n {getCollectionLabel(\n collection.collection,\n req.payload.config.collections,\n req.locale,\n )}\n </a>\n\n {displayState === 'unavailable' ? (\n <span style={{ color: '#92400e', fontSize: '13px' }}>\n {t('@jhb.software/payload-alt-text-plugin:collectionCheckFailed')}\n </span>\n ) : (\n <span style={{ fontSize: '13px', opacity: 0.7 }}>\n {t('@jhb.software/payload-alt-text-plugin:totalImageCount').replace(\n '{count}',\n String(collection.totalDocs),\n )}\n {isLocalized && (\n <>\n {' · '}\n {t('@jhb.software/payload-alt-text-plugin:localeCount').replace(\n '{count}',\n String(localeCount),\n )}\n </>\n )}\n </span>\n )}\n </div>\n\n {displayState === 'unhealthy' &&\n collection.invalidDocIds &&\n collection.invalidDocIds.length > 0 ? (\n <a\n href={`${req.payload.config.routes.admin}/collections/${collection.collection}?where[id][in]=${collection.invalidDocIds.join(',')}`}\n style={{\n background: badgeStyles.unhealthy.background,\n borderRadius: '999px',\n color: badgeStyles.unhealthy.color,\n flexShrink: 0,\n fontSize: '12px',\n fontWeight: 600,\n padding: '4px 10px',\n textDecoration: 'none',\n whiteSpace: 'nowrap',\n }}\n >\n {collection.missingDocs + collection.partialDocs}{' '}\n {t('@jhb.software/payload-alt-text-plugin:statusUnhealthy')} →\n </a>\n ) : displayState === 'healthy' ? (\n <span\n style={{\n background: badgeStyles.healthy.background,\n borderRadius: '999px',\n color: badgeStyles.healthy.color,\n flexShrink: 0,\n fontSize: '12px',\n fontWeight: 600,\n padding: '4px 10px',\n whiteSpace: 'nowrap',\n }}\n >\n {t('@jhb.software/payload-alt-text-plugin:statusHealthy')} ✓\n </span>\n ) : displayState === 'unhealthy' ? (\n <span\n style={{\n background: badgeStyles.unhealthy.background,\n borderRadius: '999px',\n color: badgeStyles.unhealthy.color,\n flexShrink: 0,\n fontSize: '12px',\n fontWeight: 600,\n padding: '4px 10px',\n whiteSpace: 'nowrap',\n }}\n >\n {collection.missingDocs + collection.partialDocs}{' '}\n {t('@jhb.software/payload-alt-text-plugin:statusUnhealthy')}\n </span>\n ) : (\n <span\n style={{\n color: '#92400e',\n flexShrink: 0,\n fontSize: '12px',\n fontWeight: 600,\n whiteSpace: 'nowrap',\n }}\n >\n {t('@jhb.software/payload-alt-text-plugin:collectionCheckFailed')}\n </span>\n )}\n </div>\n )\n })}\n </div>\n </div>\n )\n}\n"],"names":["getAltTextHealthWidgetData","getAltTextHealthWidgetDisplayState","getCollectionLabel","badgeStyles","healthy","background","color","unhealthy","AltTextHealthWidget","req","t","collections","errors","isLocalized","localeCount","totalDocs","div","className","style","display","flexDirection","gap","height","h3","fontSize","fontWeight","margin","p","opacity","length","map","collection","displayState","alignItems","border","borderRadius","justifyContent","padding","minWidth","a","href","payload","config","routes","admin","textDecoration","locale","span","replace","String","invalidDocIds","join","flexShrink","whiteSpace","missingDocs","partialDocs"],"mappings":"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"}
1
+ {"version":3,"sources":["../../src/components/AltTextHealthWidget.tsx"],"sourcesContent":["import type { TFunction } from '@payloadcms/translations'\nimport type { WidgetServerProps } from 'payload'\n\nimport { Pill } from '@payloadcms/ui/elements/Pill'\n\nimport type { PluginAltTextTranslationKeys } from '../translations/index.js'\n\nimport { getAltTextHealthWidgetData } from '../utilities/altTextHealth.js'\nimport { getAltTextHealthWidgetDisplayState } from '../utilities/altTextHealthWidgetDisplay.js'\nimport { getCollectionLabel } from '../utilities/getCollectionLabel.js'\nimport { ArrowRightIcon } from './icons/ArrowRightIcon.js'\nimport { CheckIcon } from './icons/CheckIcon.js'\nimport { ImageIcon } from './icons/ImageIcon.js'\n\nexport async function AltTextHealthWidget({ req }: WidgetServerProps) {\n const t = req.t as TFunction<PluginAltTextTranslationKeys>\n const { collections, errors, isLocalized, localeCount, totalDocs } =\n await getAltTextHealthWidgetData(req)\n\n return (\n <div\n className=\"card\"\n style={{\n display: 'flex',\n flexDirection: 'column',\n gap: '16px',\n height: '100%',\n }}\n >\n <div style={{ display: 'flex', flexDirection: 'column', gap: '4px' }}>\n <div style={{ alignItems: 'center', display: 'flex', gap: '0.5rem' }}>\n <div style={{ color: 'var(--theme-elevation-500)' }}>\n <ImageIcon />\n </div>\n <h3 style={{ margin: 0 }}>\n {t('@jhb.software/payload-alt-text-plugin:altTextHealthWidget')}\n </h3>\n </div>\n <p style={{ color: 'var(--theme-text)', fontSize: '14px', margin: 0, opacity: 0.75 }}>\n {t('@jhb.software/payload-alt-text-plugin:altTextHealthDescription')}\n </p>\n </div>\n\n {totalDocs === 0 && errors.length === 0 && (\n <p style={{ color: 'var(--theme-text)', margin: 0, opacity: 0.75 }}>\n {t('@jhb.software/payload-alt-text-plugin:noImagesFound')}\n </p>\n )}\n\n {errors.length > 0 && (\n <p style={{ color: '#92400e', fontSize: '13px', margin: 0 }}>\n {t('@jhb.software/payload-alt-text-plugin:healthCheckPartialWarning')}\n </p>\n )}\n\n <div style={{ display: 'flex', flexDirection: 'column', gap: '10px' }}>\n {collections.map((collection) => {\n const displayState = getAltTextHealthWidgetDisplayState(collection)\n\n return (\n <div\n key={collection.collection}\n style={{\n alignItems: 'center',\n background: 'var(--theme-elevation-50)',\n border: '1px solid var(--theme-border-color)',\n borderRadius: 'var(--style-radius-m)',\n display: 'flex',\n gap: '12px',\n justifyContent: 'space-between',\n padding: '12px 16px',\n }}\n >\n <div style={{ display: 'flex', flexDirection: 'column', gap: '2px', minWidth: 0 }}>\n <a\n href={`${req.payload.config.routes.admin}/collections/${collection.collection}`}\n style={{\n color: 'var(--theme-text)',\n fontSize: '14px',\n fontWeight: 500,\n textDecoration: 'none',\n }}\n >\n {getCollectionLabel(\n collection.collection,\n req.payload.config.collections,\n req.locale,\n )}\n </a>\n\n {displayState === 'unavailable' ? (\n <span style={{ color: '#92400e', fontSize: '13px' }}>\n {t('@jhb.software/payload-alt-text-plugin:collectionCheckFailed')}\n </span>\n ) : (\n <span style={{ fontSize: '13px', opacity: 0.7 }}>\n <span style={{ whiteSpace: 'nowrap' }}>\n {t('@jhb.software/payload-alt-text-plugin:totalImageCount', {\n count: collection.totalDocs,\n })}\n </span>\n {isLocalized && (\n <>\n {' · '}\n <span style={{ whiteSpace: 'nowrap' }}>\n {t('@jhb.software/payload-alt-text-plugin:localeCount', {\n count: localeCount,\n })}\n </span>\n </>\n )}\n </span>\n )}\n </div>\n\n {displayState === 'unhealthy' &&\n collection.invalidDocIds &&\n collection.invalidDocIds.length > 0 ? (\n <Pill\n pillStyle=\"error\"\n size=\"small\"\n to={`${req.payload.config.routes.admin}/collections/${collection.collection}?where[id][in]=${collection.invalidDocIds.join(',')}`}\n >\n <div style={{ alignItems: 'center', display: 'flex', gap: '0.25rem' }}>\n {t('@jhb.software/payload-alt-text-plugin:statusUnhealthy', {\n count: collection.missingDocs + collection.partialDocs,\n })}\n <ArrowRightIcon height=\"12\" width=\"12\" />\n </div>\n </Pill>\n ) : displayState === 'healthy' ? (\n <Pill pillStyle=\"success\" size=\"small\">\n <div style={{ alignItems: 'center', display: 'flex', gap: '0.25rem' }}>\n {t('@jhb.software/payload-alt-text-plugin:statusHealthy')}\n <CheckIcon height=\"12\" width=\"12\" />\n </div>\n </Pill>\n ) : displayState === 'unhealthy' ? (\n <Pill pillStyle=\"error\" size=\"small\">\n {t('@jhb.software/payload-alt-text-plugin:statusUnhealthy', {\n count: collection.missingDocs + collection.partialDocs,\n })}\n </Pill>\n ) : (\n <Pill pillStyle=\"warning\" size=\"small\">\n {t('@jhb.software/payload-alt-text-plugin:collectionCheckFailed')}\n </Pill>\n )}\n </div>\n )\n })}\n </div>\n </div>\n )\n}\n"],"names":["Pill","getAltTextHealthWidgetData","getAltTextHealthWidgetDisplayState","getCollectionLabel","ArrowRightIcon","CheckIcon","ImageIcon","AltTextHealthWidget","req","t","collections","errors","isLocalized","localeCount","totalDocs","div","className","style","display","flexDirection","gap","height","alignItems","color","h3","margin","p","fontSize","opacity","length","map","collection","displayState","background","border","borderRadius","justifyContent","padding","minWidth","a","href","payload","config","routes","admin","fontWeight","textDecoration","locale","span","whiteSpace","count","invalidDocIds","pillStyle","size","to","join","missingDocs","partialDocs","width"],"mappings":"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"}
@@ -1,5 +1,5 @@
1
1
  'use client';
2
- import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { jsx as _jsx } from "react/jsx-runtime";
3
3
  import { Button, toast, useSelection, useTranslation } from '@payloadcms/ui';
4
4
  import { useRouter } from 'next/navigation.js';
5
5
  import { useTransition } from 'react';
@@ -30,13 +30,21 @@ export function BulkGenerateAltTextsButton({ collectionSlug }) {
30
30
  }
31
31
  const data = await response.json();
32
32
  if (data.erroredDocs.length > 0) {
33
- toast.error(t('@jhb.software/payload-alt-text-plugin:failedToGenerateForXImages').replace('{X}', data.erroredDocs.length.toString()));
33
+ toast.error(t('@jhb.software/payload-alt-text-plugin:failedToGenerateForXImages', {
34
+ count: data.erroredDocs.length
35
+ }));
34
36
  }
35
37
  // in case not all images were updated, show a warning instead of a success message:
36
38
  if (data.updatedDocs === data.totalDocs) {
37
- toast.success(t('@jhb.software/payload-alt-text-plugin:xOfYImagesUpdated').replace('{X}', data.updatedDocs.toString()).replace('{Y}', data.totalDocs.toString()));
39
+ toast.success(t('@jhb.software/payload-alt-text-plugin:xOfYImagesUpdated', {
40
+ total: data.totalDocs,
41
+ updated: data.updatedDocs
42
+ }));
38
43
  } else {
39
- toast.warning(t('@jhb.software/payload-alt-text-plugin:xOfYImagesUpdated').replace('{X}', data.updatedDocs.toString()).replace('{Y}', data.totalDocs.toString()));
44
+ toast.warning(t('@jhb.software/payload-alt-text-plugin:xOfYImagesUpdated', {
45
+ total: data.totalDocs,
46
+ updated: data.updatedDocs
47
+ }));
40
48
  }
41
49
  // deselect all previously selected images
42
50
  for (const id of selectedIds){
@@ -55,18 +63,14 @@ export function BulkGenerateAltTextsButton({ collectionSlug }) {
55
63
  display: 'flex',
56
64
  justifyContent: 'right'
57
65
  },
58
- children: /*#__PURE__*/ _jsxs(Button, {
66
+ children: /*#__PURE__*/ _jsx(Button, {
59
67
  className: "m-0",
60
68
  disabled: isPending || selectedIds.length === 0,
61
69
  icon: isPending ? /*#__PURE__*/ _jsx(Spinner, {}) : /*#__PURE__*/ _jsx(Lightning, {}),
62
70
  onClick: handleGenerateAltTexts,
63
- children: [
64
- t('@jhb.software/payload-alt-text-plugin:generateAltTextFor'),
65
- " ",
66
- selectedIds.length,
67
- ' ',
68
- selectedIds.length === 1 ? t('@jhb.software/payload-alt-text-plugin:image') : t('@jhb.software/payload-alt-text-plugin:images')
69
- ]
71
+ children: t('@jhb.software/payload-alt-text-plugin:generateAltTextFor', {
72
+ count: selectedIds.length
73
+ })
70
74
  })
71
75
  });
72
76
  }
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/components/BulkGenerateAltTextsButton.tsx"],"sourcesContent":["'use client'\n\nimport { Button, toast, useSelection, useTranslation } from '@payloadcms/ui'\nimport { useRouter } from 'next/navigation.js'\nimport { useTransition } from 'react'\n\nimport type {\n PluginAltTextTranslationKeys,\n PluginAltTextTranslations,\n} from '../translations/index.js'\n\nimport { Lightning } from './icons/Lightning.js'\nimport { Spinner } from './icons/Spinner.js'\n\nexport function BulkGenerateAltTextsButton({ collectionSlug }: { collectionSlug: string }) {\n const { t } = useTranslation<PluginAltTextTranslations, PluginAltTextTranslationKeys>()\n const [isPending, startTransition] = useTransition()\n const { selected, setSelection } = useSelection()\n\n const selectedIds = Array.from(selected.entries())\n .filter(([, isSelected]) => isSelected)\n .map(([id]) => id) as string[]\n\n const router = useRouter()\n\n const handleGenerateAltTexts = () => {\n startTransition(async () => {\n if (!collectionSlug) {\n throw new Error('Collection slug is required')\n }\n\n try {\n const response = await fetch('/api/alt-text-plugin/generate/bulk', {\n body: JSON.stringify({\n collection: collectionSlug,\n ids: selectedIds,\n }),\n method: 'POST',\n })\n\n if (!response.ok) {\n toast.error(t('@jhb.software/payload-alt-text-plugin:failedToGenerate'))\n return\n }\n\n const data = (await response.json()) as {\n erroredDocs: string[]\n totalDocs: number\n updatedDocs: number\n }\n\n if (data.erroredDocs.length > 0) {\n toast.error(\n t('@jhb.software/payload-alt-text-plugin:failedToGenerateForXImages').replace(\n '{X}',\n data.erroredDocs.length.toString(),\n ),\n )\n }\n\n // in case not all images were updated, show a warning instead of a success message:\n if (data.updatedDocs === data.totalDocs) {\n toast.success(\n t('@jhb.software/payload-alt-text-plugin:xOfYImagesUpdated')\n .replace('{X}', data.updatedDocs.toString())\n .replace('{Y}', data.totalDocs.toString()),\n )\n } else {\n toast.warning(\n t('@jhb.software/payload-alt-text-plugin:xOfYImagesUpdated')\n .replace('{X}', data.updatedDocs.toString())\n .replace('{Y}', data.totalDocs.toString()),\n )\n }\n\n // deselect all previously selected images\n for (const id of selectedIds) {\n setSelection(id)\n }\n\n router.refresh()\n } catch (error) {\n console.error('Error generating alt text:', error)\n toast.error(t('@jhb.software/payload-alt-text-plugin:errorGeneratingAltText'))\n }\n })\n }\n\n return (\n selectedIds.length > 0 && (\n <div className=\"m-0\" style={{ display: 'flex', justifyContent: 'right' }}>\n <Button\n className=\"m-0\"\n disabled={isPending || selectedIds.length === 0}\n icon={isPending ? <Spinner /> : <Lightning />}\n onClick={handleGenerateAltTexts}\n >\n {t('@jhb.software/payload-alt-text-plugin:generateAltTextFor')} {selectedIds.length}{' '}\n {selectedIds.length === 1\n ? t('@jhb.software/payload-alt-text-plugin:image')\n : t('@jhb.software/payload-alt-text-plugin:images')}\n </Button>\n </div>\n )\n )\n}\n"],"names":["Button","toast","useSelection","useTranslation","useRouter","useTransition","Lightning","Spinner","BulkGenerateAltTextsButton","collectionSlug","t","isPending","startTransition","selected","setSelection","selectedIds","Array","from","entries","filter","isSelected","map","id","router","handleGenerateAltTexts","Error","response","fetch","body","JSON","stringify","collection","ids","method","ok","error","data","json","erroredDocs","length","replace","toString","updatedDocs","totalDocs","success","warning","refresh","console","div","className","style","display","justifyContent","disabled","icon","onClick"],"mappings":"AAAA;;AAEA,SAASA,MAAM,EAAEC,KAAK,EAAEC,YAAY,EAAEC,cAAc,QAAQ,iBAAgB;AAC5E,SAASC,SAAS,QAAQ,qBAAoB;AAC9C,SAASC,aAAa,QAAQ,QAAO;AAOrC,SAASC,SAAS,QAAQ,uBAAsB;AAChD,SAASC,OAAO,QAAQ,qBAAoB;AAE5C,OAAO,SAASC,2BAA2B,EAAEC,cAAc,EAA8B;IACvF,MAAM,EAAEC,CAAC,EAAE,GAAGP;IACd,MAAM,CAACQ,WAAWC,gBAAgB,GAAGP;IACrC,MAAM,EAAEQ,QAAQ,EAAEC,YAAY,EAAE,GAAGZ;IAEnC,MAAMa,cAAcC,MAAMC,IAAI,CAACJ,SAASK,OAAO,IAC5CC,MAAM,CAAC,CAAC,GAAGC,WAAW,GAAKA,YAC3BC,GAAG,CAAC,CAAC,CAACC,GAAG,GAAKA;IAEjB,MAAMC,SAASnB;IAEf,MAAMoB,yBAAyB;QAC7BZ,gBAAgB;YACd,IAAI,CAACH,gBAAgB;gBACnB,MAAM,IAAIgB,MAAM;YAClB;YAEA,IAAI;gBACF,MAAMC,WAAW,MAAMC,MAAM,sCAAsC;oBACjEC,MAAMC,KAAKC,SAAS,CAAC;wBACnBC,YAAYtB;wBACZuB,KAAKjB;oBACP;oBACAkB,QAAQ;gBACV;gBAEA,IAAI,CAACP,SAASQ,EAAE,EAAE;oBAChBjC,MAAMkC,KAAK,CAACzB,EAAE;oBACd;gBACF;gBAEA,MAAM0B,OAAQ,MAAMV,SAASW,IAAI;gBAMjC,IAAID,KAAKE,WAAW,CAACC,MAAM,GAAG,GAAG;oBAC/BtC,MAAMkC,KAAK,CACTzB,EAAE,oEAAoE8B,OAAO,CAC3E,OACAJ,KAAKE,WAAW,CAACC,MAAM,CAACE,QAAQ;gBAGtC;gBAEA,oFAAoF;gBACpF,IAAIL,KAAKM,WAAW,KAAKN,KAAKO,SAAS,EAAE;oBACvC1C,MAAM2C,OAAO,CACXlC,EAAE,2DACC8B,OAAO,CAAC,OAAOJ,KAAKM,WAAW,CAACD,QAAQ,IACxCD,OAAO,CAAC,OAAOJ,KAAKO,SAAS,CAACF,QAAQ;gBAE7C,OAAO;oBACLxC,MAAM4C,OAAO,CACXnC,EAAE,2DACC8B,OAAO,CAAC,OAAOJ,KAAKM,WAAW,CAACD,QAAQ,IACxCD,OAAO,CAAC,OAAOJ,KAAKO,SAAS,CAACF,QAAQ;gBAE7C;gBAEA,0CAA0C;gBAC1C,KAAK,MAAMnB,MAAMP,YAAa;oBAC5BD,aAAaQ;gBACf;gBAEAC,OAAOuB,OAAO;YAChB,EAAE,OAAOX,OAAO;gBACdY,QAAQZ,KAAK,CAAC,8BAA8BA;gBAC5ClC,MAAMkC,KAAK,CAACzB,EAAE;YAChB;QACF;IACF;IAEA,OACEK,YAAYwB,MAAM,GAAG,mBACnB,KAACS;QAAIC,WAAU;QAAMC,OAAO;YAAEC,SAAS;YAAQC,gBAAgB;QAAQ;kBACrE,cAAA,MAACpD;YACCiD,WAAU;YACVI,UAAU1C,aAAaI,YAAYwB,MAAM,KAAK;YAC9Ce,MAAM3C,0BAAY,KAACJ,6BAAa,KAACD;YACjCiD,SAAS/B;;gBAERd,EAAE;gBAA4D;gBAAEK,YAAYwB,MAAM;gBAAE;gBACpFxB,YAAYwB,MAAM,KAAK,IACpB7B,EAAE,iDACFA,EAAE;;;;AAKhB"}
1
+ {"version":3,"sources":["../../src/components/BulkGenerateAltTextsButton.tsx"],"sourcesContent":["'use client'\n\nimport { Button, toast, useSelection, useTranslation } from '@payloadcms/ui'\nimport { useRouter } from 'next/navigation.js'\nimport { useTransition } from 'react'\n\nimport type {\n PluginAltTextTranslationKeys,\n PluginAltTextTranslations,\n} from '../translations/index.js'\n\nimport { Lightning } from './icons/Lightning.js'\nimport { Spinner } from './icons/Spinner.js'\n\nexport function BulkGenerateAltTextsButton({ collectionSlug }: { collectionSlug: string }) {\n const { t } = useTranslation<PluginAltTextTranslations, PluginAltTextTranslationKeys>()\n const [isPending, startTransition] = useTransition()\n const { selected, setSelection } = useSelection()\n\n const selectedIds = Array.from(selected.entries())\n .filter(([, isSelected]) => isSelected)\n .map(([id]) => id) as string[]\n\n const router = useRouter()\n\n const handleGenerateAltTexts = () => {\n startTransition(async () => {\n if (!collectionSlug) {\n throw new Error('Collection slug is required')\n }\n\n try {\n const response = await fetch('/api/alt-text-plugin/generate/bulk', {\n body: JSON.stringify({\n collection: collectionSlug,\n ids: selectedIds,\n }),\n method: 'POST',\n })\n\n if (!response.ok) {\n toast.error(t('@jhb.software/payload-alt-text-plugin:failedToGenerate'))\n return\n }\n\n const data = (await response.json()) as {\n erroredDocs: string[]\n totalDocs: number\n updatedDocs: number\n }\n\n if (data.erroredDocs.length > 0) {\n toast.error(\n t('@jhb.software/payload-alt-text-plugin:failedToGenerateForXImages', {\n count: data.erroredDocs.length,\n }),\n )\n }\n\n // in case not all images were updated, show a warning instead of a success message:\n if (data.updatedDocs === data.totalDocs) {\n toast.success(\n t('@jhb.software/payload-alt-text-plugin:xOfYImagesUpdated', {\n total: data.totalDocs,\n updated: data.updatedDocs,\n }),\n )\n } else {\n toast.warning(\n t('@jhb.software/payload-alt-text-plugin:xOfYImagesUpdated', {\n total: data.totalDocs,\n updated: data.updatedDocs,\n }),\n )\n }\n\n // deselect all previously selected images\n for (const id of selectedIds) {\n setSelection(id)\n }\n\n router.refresh()\n } catch (error) {\n console.error('Error generating alt text:', error)\n toast.error(t('@jhb.software/payload-alt-text-plugin:errorGeneratingAltText'))\n }\n })\n }\n\n return (\n selectedIds.length > 0 && (\n <div className=\"m-0\" style={{ display: 'flex', justifyContent: 'right' }}>\n <Button\n className=\"m-0\"\n disabled={isPending || selectedIds.length === 0}\n icon={isPending ? <Spinner /> : <Lightning />}\n onClick={handleGenerateAltTexts}\n >\n {t('@jhb.software/payload-alt-text-plugin:generateAltTextFor', {\n count: selectedIds.length,\n })}\n </Button>\n </div>\n )\n )\n}\n"],"names":["Button","toast","useSelection","useTranslation","useRouter","useTransition","Lightning","Spinner","BulkGenerateAltTextsButton","collectionSlug","t","isPending","startTransition","selected","setSelection","selectedIds","Array","from","entries","filter","isSelected","map","id","router","handleGenerateAltTexts","Error","response","fetch","body","JSON","stringify","collection","ids","method","ok","error","data","json","erroredDocs","length","count","updatedDocs","totalDocs","success","total","updated","warning","refresh","console","div","className","style","display","justifyContent","disabled","icon","onClick"],"mappings":"AAAA;;AAEA,SAASA,MAAM,EAAEC,KAAK,EAAEC,YAAY,EAAEC,cAAc,QAAQ,iBAAgB;AAC5E,SAASC,SAAS,QAAQ,qBAAoB;AAC9C,SAASC,aAAa,QAAQ,QAAO;AAOrC,SAASC,SAAS,QAAQ,uBAAsB;AAChD,SAASC,OAAO,QAAQ,qBAAoB;AAE5C,OAAO,SAASC,2BAA2B,EAAEC,cAAc,EAA8B;IACvF,MAAM,EAAEC,CAAC,EAAE,GAAGP;IACd,MAAM,CAACQ,WAAWC,gBAAgB,GAAGP;IACrC,MAAM,EAAEQ,QAAQ,EAAEC,YAAY,EAAE,GAAGZ;IAEnC,MAAMa,cAAcC,MAAMC,IAAI,CAACJ,SAASK,OAAO,IAC5CC,MAAM,CAAC,CAAC,GAAGC,WAAW,GAAKA,YAC3BC,GAAG,CAAC,CAAC,CAACC,GAAG,GAAKA;IAEjB,MAAMC,SAASnB;IAEf,MAAMoB,yBAAyB;QAC7BZ,gBAAgB;YACd,IAAI,CAACH,gBAAgB;gBACnB,MAAM,IAAIgB,MAAM;YAClB;YAEA,IAAI;gBACF,MAAMC,WAAW,MAAMC,MAAM,sCAAsC;oBACjEC,MAAMC,KAAKC,SAAS,CAAC;wBACnBC,YAAYtB;wBACZuB,KAAKjB;oBACP;oBACAkB,QAAQ;gBACV;gBAEA,IAAI,CAACP,SAASQ,EAAE,EAAE;oBAChBjC,MAAMkC,KAAK,CAACzB,EAAE;oBACd;gBACF;gBAEA,MAAM0B,OAAQ,MAAMV,SAASW,IAAI;gBAMjC,IAAID,KAAKE,WAAW,CAACC,MAAM,GAAG,GAAG;oBAC/BtC,MAAMkC,KAAK,CACTzB,EAAE,oEAAoE;wBACpE8B,OAAOJ,KAAKE,WAAW,CAACC,MAAM;oBAChC;gBAEJ;gBAEA,oFAAoF;gBACpF,IAAIH,KAAKK,WAAW,KAAKL,KAAKM,SAAS,EAAE;oBACvCzC,MAAM0C,OAAO,CACXjC,EAAE,2DAA2D;wBAC3DkC,OAAOR,KAAKM,SAAS;wBACrBG,SAAST,KAAKK,WAAW;oBAC3B;gBAEJ,OAAO;oBACLxC,MAAM6C,OAAO,CACXpC,EAAE,2DAA2D;wBAC3DkC,OAAOR,KAAKM,SAAS;wBACrBG,SAAST,KAAKK,WAAW;oBAC3B;gBAEJ;gBAEA,0CAA0C;gBAC1C,KAAK,MAAMnB,MAAMP,YAAa;oBAC5BD,aAAaQ;gBACf;gBAEAC,OAAOwB,OAAO;YAChB,EAAE,OAAOZ,OAAO;gBACda,QAAQb,KAAK,CAAC,8BAA8BA;gBAC5ClC,MAAMkC,KAAK,CAACzB,EAAE;YAChB;QACF;IACF;IAEA,OACEK,YAAYwB,MAAM,GAAG,mBACnB,KAACU;QAAIC,WAAU;QAAMC,OAAO;YAAEC,SAAS;YAAQC,gBAAgB;QAAQ;kBACrE,cAAA,KAACrD;YACCkD,WAAU;YACVI,UAAU3C,aAAaI,YAAYwB,MAAM,KAAK;YAC9CgB,MAAM5C,0BAAY,KAACJ,6BAAa,KAACD;YACjCkD,SAAShC;sBAERd,EAAE,4DAA4D;gBAC7D8B,OAAOzB,YAAYwB,MAAM;YAC3B;;;AAKV"}
@@ -1 +1,3 @@
1
- export declare function GenerateAltTextButton(): import("react").JSX.Element;
1
+ export declare function GenerateAltTextButton({ supportedMimeTypes }: {
2
+ supportedMimeTypes?: string[];
3
+ }): import("react").JSX.Element;
@@ -4,7 +4,7 @@ import { Button, toast, useDocumentInfo, useField, useLocale, useTranslation } f
4
4
  import { useTransition } from 'react';
5
5
  import { Lightning } from './icons/Lightning.js';
6
6
  import { Spinner } from './icons/Spinner.js';
7
- export function GenerateAltTextButton() {
7
+ export function GenerateAltTextButton({ supportedMimeTypes }) {
8
8
  const { t } = useTranslation();
9
9
  const { id, collectionSlug } = useDocumentInfo();
10
10
  const locale = useLocale();
@@ -15,6 +15,10 @@ export function GenerateAltTextButton() {
15
15
  const { setValue: setAltText } = useField({
16
16
  path: 'alt'
17
17
  });
18
+ const { value: mimeType } = useField({
19
+ path: 'mimeType'
20
+ });
21
+ const isUnsupportedMimeType = !!mimeType && !!supportedMimeTypes && !supportedMimeTypes.includes(mimeType);
18
22
  const handleGenerateAltText = ()=>{
19
23
  if (!collectionSlug || !id) {
20
24
  toast.error(t('@jhb.software/payload-alt-text-plugin:cannotGenerateMissingFields'));
@@ -96,10 +100,12 @@ export function GenerateAltTextButton() {
96
100
  display: 'flex'
97
101
  },
98
102
  children: /*#__PURE__*/ _jsx(Button, {
99
- disabled: isPending || !id,
103
+ disabled: isPending || !id || isUnsupportedMimeType,
100
104
  icon: isPending ? /*#__PURE__*/ _jsx(Spinner, {}) : /*#__PURE__*/ _jsx(Lightning, {}),
101
105
  onClick: handleGenerateAltText,
102
- tooltip: !id ? t('@jhb.software/payload-alt-text-plugin:pleaseSaveDocumentFirst') : undefined,
106
+ tooltip: isUnsupportedMimeType ? t('@jhb.software/payload-alt-text-plugin:unsupportedMimeType', {
107
+ mimeType
108
+ }) : !id ? t('@jhb.software/payload-alt-text-plugin:pleaseSaveDocumentFirst') : undefined,
103
109
  children: t('@jhb.software/payload-alt-text-plugin:generateAltText')
104
110
  })
105
111
  })
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/components/GenerateAltTextButton.tsx"],"sourcesContent":["'use client'\n\nimport { Button, toast, useDocumentInfo, useField, useLocale, useTranslation } from '@payloadcms/ui'\nimport { useTransition } from 'react'\n\nimport type {\n PluginAltTextTranslationKeys,\n PluginAltTextTranslations,\n} from '../translations/index.js'\n\nimport { Lightning } from './icons/Lightning.js'\nimport { Spinner } from './icons/Spinner.js'\n\nexport function GenerateAltTextButton() {\n const { t } = useTranslation<PluginAltTextTranslations, PluginAltTextTranslationKeys>()\n const { id, collectionSlug } = useDocumentInfo()\n const locale = useLocale()\n const [isPending, startTransition] = useTransition()\n\n const { setValue: setKeywords } = useField<string>({ path: 'keywords' })\n const { setValue: setAltText } = useField<string>({ path: 'alt' })\n\n const handleGenerateAltText = () => {\n if (!collectionSlug || !id) {\n toast.error(t('@jhb.software/payload-alt-text-plugin:cannotGenerateMissingFields'))\n throw new Error('Missing required fields')\n }\n\n startTransition(async () => {\n try {\n const response = await fetch('/api/alt-text-plugin/generate', {\n body: JSON.stringify({\n id: id as string,\n collection: collectionSlug,\n locale: locale?.code ?? null, // sent null when localization is disabled\n }),\n method: 'POST',\n })\n\n if (!response.ok) {\n let errorMessage = t('@jhb.software/payload-alt-text-plugin:failedToGenerate')\n try {\n const errorData = (await response.json()) as { error: string }\n errorMessage = errorData.error\n } catch (error) {\n console.error('Error generating alt text:', error)\n }\n\n toast.error(errorMessage)\n return\n }\n\n const data = (await response.json()) as {\n altText: string\n keywords: string[]\n }\n\n if (data.altText && data.keywords) {\n setAltText(data.altText)\n setKeywords(data.keywords)\n toast.success(t('@jhb.software/payload-alt-text-plugin:altTextGeneratedSuccess'))\n } else {\n toast.error(t('@jhb.software/payload-alt-text-plugin:noAltTextGenerated'))\n }\n } catch (error) {\n console.error('Error generating alt text:', error)\n toast.error(t('@jhb.software/payload-alt-text-plugin:errorGeneratingAltText'))\n }\n })\n }\n\n return (\n <div style={{ display: 'flex', gap: '20px', marginTop: '10px' }}>\n <div style={{ color: 'var(--theme-elevation-400)', flex: '1' }}>\n <p>{t('@jhb.software/payload-alt-text-plugin:altTextDescription')}</p>\n <ol style={{ margin: '10px 0', paddingLeft: '20px' }}>\n <li>{t('@jhb.software/payload-alt-text-plugin:altTextRequirement1')}</li>\n <li>{t('@jhb.software/payload-alt-text-plugin:altTextRequirement2')}</li>\n <li>{t('@jhb.software/payload-alt-text-plugin:altTextRequirement3')}</li>\n </ol>\n </div>\n <div style={{ alignItems: 'center', display: 'flex' }}>\n <Button\n disabled={isPending || !id}\n icon={isPending ? <Spinner /> : <Lightning />}\n onClick={handleGenerateAltText}\n tooltip={\n !id ? t('@jhb.software/payload-alt-text-plugin:pleaseSaveDocumentFirst') : undefined\n }\n >\n {t('@jhb.software/payload-alt-text-plugin:generateAltText')}\n </Button>\n </div>\n </div>\n )\n}\n"],"names":["Button","toast","useDocumentInfo","useField","useLocale","useTranslation","useTransition","Lightning","Spinner","GenerateAltTextButton","t","id","collectionSlug","locale","isPending","startTransition","setValue","setKeywords","path","setAltText","handleGenerateAltText","error","Error","response","fetch","body","JSON","stringify","collection","code","method","ok","errorMessage","errorData","json","console","data","altText","keywords","success","div","style","display","gap","marginTop","color","flex","p","ol","margin","paddingLeft","li","alignItems","disabled","icon","onClick","tooltip","undefined"],"mappings":"AAAA;;AAEA,SAASA,MAAM,EAAEC,KAAK,EAAEC,eAAe,EAAEC,QAAQ,EAAEC,SAAS,EAAEC,cAAc,QAAQ,iBAAgB;AACpG,SAASC,aAAa,QAAQ,QAAO;AAOrC,SAASC,SAAS,QAAQ,uBAAsB;AAChD,SAASC,OAAO,QAAQ,qBAAoB;AAE5C,OAAO,SAASC;IACd,MAAM,EAAEC,CAAC,EAAE,GAAGL;IACd,MAAM,EAAEM,EAAE,EAAEC,cAAc,EAAE,GAAGV;IAC/B,MAAMW,SAAST;IACf,MAAM,CAACU,WAAWC,gBAAgB,GAAGT;IAErC,MAAM,EAAEU,UAAUC,WAAW,EAAE,GAAGd,SAAiB;QAAEe,MAAM;IAAW;IACtE,MAAM,EAAEF,UAAUG,UAAU,EAAE,GAAGhB,SAAiB;QAAEe,MAAM;IAAM;IAEhE,MAAME,wBAAwB;QAC5B,IAAI,CAACR,kBAAkB,CAACD,IAAI;YAC1BV,MAAMoB,KAAK,CAACX,EAAE;YACd,MAAM,IAAIY,MAAM;QAClB;QAEAP,gBAAgB;YACd,IAAI;gBACF,MAAMQ,WAAW,MAAMC,MAAM,iCAAiC;oBAC5DC,MAAMC,KAAKC,SAAS,CAAC;wBACnBhB,IAAIA;wBACJiB,YAAYhB;wBACZC,QAAQA,QAAQgB,QAAQ;oBAC1B;oBACAC,QAAQ;gBACV;gBAEA,IAAI,CAACP,SAASQ,EAAE,EAAE;oBAChB,IAAIC,eAAetB,EAAE;oBACrB,IAAI;wBACF,MAAMuB,YAAa,MAAMV,SAASW,IAAI;wBACtCF,eAAeC,UAAUZ,KAAK;oBAChC,EAAE,OAAOA,OAAO;wBACdc,QAAQd,KAAK,CAAC,8BAA8BA;oBAC9C;oBAEApB,MAAMoB,KAAK,CAACW;oBACZ;gBACF;gBAEA,MAAMI,OAAQ,MAAMb,SAASW,IAAI;gBAKjC,IAAIE,KAAKC,OAAO,IAAID,KAAKE,QAAQ,EAAE;oBACjCnB,WAAWiB,KAAKC,OAAO;oBACvBpB,YAAYmB,KAAKE,QAAQ;oBACzBrC,MAAMsC,OAAO,CAAC7B,EAAE;gBAClB,OAAO;oBACLT,MAAMoB,KAAK,CAACX,EAAE;gBAChB;YACF,EAAE,OAAOW,OAAO;gBACdc,QAAQd,KAAK,CAAC,8BAA8BA;gBAC5CpB,MAAMoB,KAAK,CAACX,EAAE;YAChB;QACF;IACF;IAEA,qBACE,MAAC8B;QAAIC,OAAO;YAAEC,SAAS;YAAQC,KAAK;YAAQC,WAAW;QAAO;;0BAC5D,MAACJ;gBAAIC,OAAO;oBAAEI,OAAO;oBAA8BC,MAAM;gBAAI;;kCAC3D,KAACC;kCAAGrC,EAAE;;kCACN,MAACsC;wBAAGP,OAAO;4BAAEQ,QAAQ;4BAAUC,aAAa;wBAAO;;0CACjD,KAACC;0CAAIzC,EAAE;;0CACP,KAACyC;0CAAIzC,EAAE;;0CACP,KAACyC;0CAAIzC,EAAE;;;;;;0BAGX,KAAC8B;gBAAIC,OAAO;oBAAEW,YAAY;oBAAUV,SAAS;gBAAO;0BAClD,cAAA,KAAC1C;oBACCqD,UAAUvC,aAAa,CAACH;oBACxB2C,MAAMxC,0BAAY,KAACN,6BAAa,KAACD;oBACjCgD,SAASnC;oBACToC,SACE,CAAC7C,KAAKD,EAAE,mEAAmE+C;8BAG5E/C,EAAE;;;;;AAKb"}
1
+ {"version":3,"sources":["../../src/components/GenerateAltTextButton.tsx"],"sourcesContent":["'use client'\n\nimport { Button, toast, useDocumentInfo, useField, useLocale, useTranslation } from '@payloadcms/ui'\nimport { useTransition } from 'react'\n\nimport type {\n PluginAltTextTranslationKeys,\n PluginAltTextTranslations,\n} from '../translations/index.js'\n\nimport { Lightning } from './icons/Lightning.js'\nimport { Spinner } from './icons/Spinner.js'\n\nexport function GenerateAltTextButton({ supportedMimeTypes }: { supportedMimeTypes?: string[] }) {\n const { t } = useTranslation<PluginAltTextTranslations, PluginAltTextTranslationKeys>()\n const { id, collectionSlug } = useDocumentInfo()\n const locale = useLocale()\n const [isPending, startTransition] = useTransition()\n\n const { setValue: setKeywords } = useField<string>({ path: 'keywords' })\n const { setValue: setAltText } = useField<string>({ path: 'alt' })\n const { value: mimeType } = useField<string>({ path: 'mimeType' })\n\n const isUnsupportedMimeType =\n !!mimeType && !!supportedMimeTypes && !supportedMimeTypes.includes(mimeType)\n\n const handleGenerateAltText = () => {\n if (!collectionSlug || !id) {\n toast.error(t('@jhb.software/payload-alt-text-plugin:cannotGenerateMissingFields'))\n throw new Error('Missing required fields')\n }\n\n startTransition(async () => {\n try {\n const response = await fetch('/api/alt-text-plugin/generate', {\n body: JSON.stringify({\n id: id as string,\n collection: collectionSlug,\n locale: locale?.code ?? null, // sent null when localization is disabled\n }),\n method: 'POST',\n })\n\n if (!response.ok) {\n let errorMessage = t('@jhb.software/payload-alt-text-plugin:failedToGenerate')\n try {\n const errorData = (await response.json()) as { error: string }\n errorMessage = errorData.error\n } catch (error) {\n console.error('Error generating alt text:', error)\n }\n\n toast.error(errorMessage)\n return\n }\n\n const data = (await response.json()) as {\n altText: string\n keywords: string[]\n }\n\n if (data.altText && data.keywords) {\n setAltText(data.altText)\n setKeywords(data.keywords)\n toast.success(t('@jhb.software/payload-alt-text-plugin:altTextGeneratedSuccess'))\n } else {\n toast.error(t('@jhb.software/payload-alt-text-plugin:noAltTextGenerated'))\n }\n } catch (error) {\n console.error('Error generating alt text:', error)\n toast.error(t('@jhb.software/payload-alt-text-plugin:errorGeneratingAltText'))\n }\n })\n }\n\n return (\n <div style={{ display: 'flex', gap: '20px', marginTop: '10px' }}>\n <div style={{ color: 'var(--theme-elevation-400)', flex: '1' }}>\n <p>{t('@jhb.software/payload-alt-text-plugin:altTextDescription')}</p>\n <ol style={{ margin: '10px 0', paddingLeft: '20px' }}>\n <li>{t('@jhb.software/payload-alt-text-plugin:altTextRequirement1')}</li>\n <li>{t('@jhb.software/payload-alt-text-plugin:altTextRequirement2')}</li>\n <li>{t('@jhb.software/payload-alt-text-plugin:altTextRequirement3')}</li>\n </ol>\n </div>\n <div style={{ alignItems: 'center', display: 'flex' }}>\n <Button\n disabled={isPending || !id || isUnsupportedMimeType}\n icon={isPending ? <Spinner /> : <Lightning />}\n onClick={handleGenerateAltText}\n tooltip={\n isUnsupportedMimeType\n ? t('@jhb.software/payload-alt-text-plugin:unsupportedMimeType', { mimeType })\n : !id\n ? t('@jhb.software/payload-alt-text-plugin:pleaseSaveDocumentFirst')\n : undefined\n }\n >\n {t('@jhb.software/payload-alt-text-plugin:generateAltText')}\n </Button>\n </div>\n </div>\n )\n}\n"],"names":["Button","toast","useDocumentInfo","useField","useLocale","useTranslation","useTransition","Lightning","Spinner","GenerateAltTextButton","supportedMimeTypes","t","id","collectionSlug","locale","isPending","startTransition","setValue","setKeywords","path","setAltText","value","mimeType","isUnsupportedMimeType","includes","handleGenerateAltText","error","Error","response","fetch","body","JSON","stringify","collection","code","method","ok","errorMessage","errorData","json","console","data","altText","keywords","success","div","style","display","gap","marginTop","color","flex","p","ol","margin","paddingLeft","li","alignItems","disabled","icon","onClick","tooltip","undefined"],"mappings":"AAAA;;AAEA,SAASA,MAAM,EAAEC,KAAK,EAAEC,eAAe,EAAEC,QAAQ,EAAEC,SAAS,EAAEC,cAAc,QAAQ,iBAAgB;AACpG,SAASC,aAAa,QAAQ,QAAO;AAOrC,SAASC,SAAS,QAAQ,uBAAsB;AAChD,SAASC,OAAO,QAAQ,qBAAoB;AAE5C,OAAO,SAASC,sBAAsB,EAAEC,kBAAkB,EAAqC;IAC7F,MAAM,EAAEC,CAAC,EAAE,GAAGN;IACd,MAAM,EAAEO,EAAE,EAAEC,cAAc,EAAE,GAAGX;IAC/B,MAAMY,SAASV;IACf,MAAM,CAACW,WAAWC,gBAAgB,GAAGV;IAErC,MAAM,EAAEW,UAAUC,WAAW,EAAE,GAAGf,SAAiB;QAAEgB,MAAM;IAAW;IACtE,MAAM,EAAEF,UAAUG,UAAU,EAAE,GAAGjB,SAAiB;QAAEgB,MAAM;IAAM;IAChE,MAAM,EAAEE,OAAOC,QAAQ,EAAE,GAAGnB,SAAiB;QAAEgB,MAAM;IAAW;IAEhE,MAAMI,wBACJ,CAAC,CAACD,YAAY,CAAC,CAACZ,sBAAsB,CAACA,mBAAmBc,QAAQ,CAACF;IAErE,MAAMG,wBAAwB;QAC5B,IAAI,CAACZ,kBAAkB,CAACD,IAAI;YAC1BX,MAAMyB,KAAK,CAACf,EAAE;YACd,MAAM,IAAIgB,MAAM;QAClB;QAEAX,gBAAgB;YACd,IAAI;gBACF,MAAMY,WAAW,MAAMC,MAAM,iCAAiC;oBAC5DC,MAAMC,KAAKC,SAAS,CAAC;wBACnBpB,IAAIA;wBACJqB,YAAYpB;wBACZC,QAAQA,QAAQoB,QAAQ;oBAC1B;oBACAC,QAAQ;gBACV;gBAEA,IAAI,CAACP,SAASQ,EAAE,EAAE;oBAChB,IAAIC,eAAe1B,EAAE;oBACrB,IAAI;wBACF,MAAM2B,YAAa,MAAMV,SAASW,IAAI;wBACtCF,eAAeC,UAAUZ,KAAK;oBAChC,EAAE,OAAOA,OAAO;wBACdc,QAAQd,KAAK,CAAC,8BAA8BA;oBAC9C;oBAEAzB,MAAMyB,KAAK,CAACW;oBACZ;gBACF;gBAEA,MAAMI,OAAQ,MAAMb,SAASW,IAAI;gBAKjC,IAAIE,KAAKC,OAAO,IAAID,KAAKE,QAAQ,EAAE;oBACjCvB,WAAWqB,KAAKC,OAAO;oBACvBxB,YAAYuB,KAAKE,QAAQ;oBACzB1C,MAAM2C,OAAO,CAACjC,EAAE;gBAClB,OAAO;oBACLV,MAAMyB,KAAK,CAACf,EAAE;gBAChB;YACF,EAAE,OAAOe,OAAO;gBACdc,QAAQd,KAAK,CAAC,8BAA8BA;gBAC5CzB,MAAMyB,KAAK,CAACf,EAAE;YAChB;QACF;IACF;IAEA,qBACE,MAACkC;QAAIC,OAAO;YAAEC,SAAS;YAAQC,KAAK;YAAQC,WAAW;QAAO;;0BAC5D,MAACJ;gBAAIC,OAAO;oBAAEI,OAAO;oBAA8BC,MAAM;gBAAI;;kCAC3D,KAACC;kCAAGzC,EAAE;;kCACN,MAAC0C;wBAAGP,OAAO;4BAAEQ,QAAQ;4BAAUC,aAAa;wBAAO;;0CACjD,KAACC;0CAAI7C,EAAE;;0CACP,KAAC6C;0CAAI7C,EAAE;;0CACP,KAAC6C;0CAAI7C,EAAE;;;;;;0BAGX,KAACkC;gBAAIC,OAAO;oBAAEW,YAAY;oBAAUV,SAAS;gBAAO;0BAClD,cAAA,KAAC/C;oBACC0D,UAAU3C,aAAa,CAACH,MAAMW;oBAC9BoC,MAAM5C,0BAAY,KAACP,6BAAa,KAACD;oBACjCqD,SAASnC;oBACToC,SACEtC,wBACIZ,EAAE,6DAA6D;wBAAEW;oBAAS,KAC1E,CAACV,KACCD,EAAE,mEACFmD;8BAGPnD,EAAE;;;;;AAKb"}
@@ -0,0 +1,2 @@
1
+ import React from 'react';
2
+ export declare const ArrowRightIcon: React.FC<React.SVGProps<SVGSVGElement>>;
@@ -0,0 +1,21 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import React from 'react';
3
+ export const ArrowRightIcon = (props)=>/*#__PURE__*/ _jsx("svg", {
4
+ "data-testid": "geist-icon",
5
+ height: "16",
6
+ strokeLinejoin: "round",
7
+ style: {
8
+ color: 'currentcolor'
9
+ },
10
+ viewBox: "0 0 16 16",
11
+ width: "16",
12
+ ...props,
13
+ children: /*#__PURE__*/ _jsx("path", {
14
+ clipRule: "evenodd",
15
+ d: "M9.53 2.22L9 1.69 7.94 2.75l.53.53 3.97 3.97H1v1.5h11.44l-3.97 3.97-.53.53L9 14.31l.53-.53 5.074-5.073a1 1 0 000-1.414L9.53 2.22z",
16
+ fill: "currentColor",
17
+ fillRule: "evenodd"
18
+ })
19
+ });
20
+
21
+ //# sourceMappingURL=ArrowRightIcon.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../src/components/icons/ArrowRightIcon.tsx"],"sourcesContent":["import React from 'react'\n\nexport const ArrowRightIcon: React.FC<React.SVGProps<SVGSVGElement>> = (props) => (\n <svg\n data-testid=\"geist-icon\"\n height=\"16\"\n strokeLinejoin=\"round\"\n style={{ color: 'currentcolor' }}\n viewBox=\"0 0 16 16\"\n width=\"16\"\n {...props}\n >\n <path\n clipRule=\"evenodd\"\n d=\"M9.53 2.22L9 1.69 7.94 2.75l.53.53 3.97 3.97H1v1.5h11.44l-3.97 3.97-.53.53L9 14.31l.53-.53 5.074-5.073a1 1 0 000-1.414L9.53 2.22z\"\n fill=\"currentColor\"\n fillRule=\"evenodd\"\n />\n </svg>\n)\n"],"names":["React","ArrowRightIcon","props","svg","data-testid","height","strokeLinejoin","style","color","viewBox","width","path","clipRule","d","fill","fillRule"],"mappings":";AAAA,OAAOA,WAAW,QAAO;AAEzB,OAAO,MAAMC,iBAA0D,CAACC,sBACtE,KAACC;QACCC,eAAY;QACZC,QAAO;QACPC,gBAAe;QACfC,OAAO;YAAEC,OAAO;QAAe;QAC/BC,SAAQ;QACRC,OAAM;QACL,GAAGR,KAAK;kBAET,cAAA,KAACS;YACCC,UAAS;YACTC,GAAE;YACFC,MAAK;YACLC,UAAS;;OAGd"}
@@ -0,0 +1,2 @@
1
+ import React from 'react';
2
+ export declare const CheckIcon: React.FC<React.SVGProps<SVGSVGElement>>;
@@ -0,0 +1,21 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import React from 'react';
3
+ export const CheckIcon = (props)=>/*#__PURE__*/ _jsx("svg", {
4
+ "data-testid": "geist-icon",
5
+ height: "16",
6
+ strokeLinejoin: "round",
7
+ style: {
8
+ color: 'currentcolor'
9
+ },
10
+ viewBox: "0 0 16 16",
11
+ width: "16",
12
+ ...props,
13
+ children: /*#__PURE__*/ _jsx("path", {
14
+ clipRule: "evenodd",
15
+ d: "M15.56 4l-.53.53-8.793 8.793a1.75 1.75 0 01-2.474 0l.53-.53-.53.53L.97 10.53.44 10 1.5 8.94l.53.53 2.793 2.793a.25.25 0 00.354 0L13.97 3.47l.53-.53L15.56 4z",
16
+ fill: "currentColor",
17
+ fillRule: "evenodd"
18
+ })
19
+ });
20
+
21
+ //# sourceMappingURL=CheckIcon.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../src/components/icons/CheckIcon.tsx"],"sourcesContent":["import React from 'react'\n\nexport const CheckIcon: React.FC<React.SVGProps<SVGSVGElement>> = (props) => (\n <svg\n data-testid=\"geist-icon\"\n height=\"16\"\n strokeLinejoin=\"round\"\n style={{ color: 'currentcolor' }}\n viewBox=\"0 0 16 16\"\n width=\"16\"\n {...props}\n >\n <path\n clipRule=\"evenodd\"\n d=\"M15.56 4l-.53.53-8.793 8.793a1.75 1.75 0 01-2.474 0l.53-.53-.53.53L.97 10.53.44 10 1.5 8.94l.53.53 2.793 2.793a.25.25 0 00.354 0L13.97 3.47l.53-.53L15.56 4z\"\n fill=\"currentColor\"\n fillRule=\"evenodd\"\n />\n </svg>\n)\n"],"names":["React","CheckIcon","props","svg","data-testid","height","strokeLinejoin","style","color","viewBox","width","path","clipRule","d","fill","fillRule"],"mappings":";AAAA,OAAOA,WAAW,QAAO;AAEzB,OAAO,MAAMC,YAAqD,CAACC,sBACjE,KAACC;QACCC,eAAY;QACZC,QAAO;QACPC,gBAAe;QACfC,OAAO;YAAEC,OAAO;QAAe;QAC/BC,SAAQ;QACRC,OAAM;QACL,GAAGR,KAAK;kBAET,cAAA,KAACS;YACCC,UAAS;YACTC,GAAE;YACFC,MAAK;YACLC,UAAS;;OAGd"}
@@ -0,0 +1,2 @@
1
+ import React from 'react';
2
+ export declare const ImageIcon: React.FC<React.SVGProps<SVGSVGElement>>;
@@ -0,0 +1,21 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import React from 'react';
3
+ export const ImageIcon = (props)=>/*#__PURE__*/ _jsx("svg", {
4
+ "data-testid": "geist-icon",
5
+ height: "16",
6
+ strokeLinejoin: "round",
7
+ style: {
8
+ color: 'currentcolor'
9
+ },
10
+ viewBox: "0 0 16 16",
11
+ width: "16",
12
+ ...props,
13
+ children: /*#__PURE__*/ _jsx("path", {
14
+ clipRule: "evenodd",
15
+ d: "M14.5 2.5h-13v6.69l1.47-1.47.22-.22h3.75l.03-.03 3.5-3.5h1.06l2.97 2.97V2.5zM8 8.56l1.53 1.53.53.53L9 11.68l-.53-.53L6.32 9H3.81l-2.28 2.28-.03.03v1.19a1 1 0 001 1h11a1 1 0 001-1V9.06L11 5.56 8.03 8.53 8 8.56zm-8 2.25v1.69A2.5 2.5 0 002.5 15h11a2.5 2.5 0 002.5-2.5V9.56l.56-.56-.53-.53-.03-.03V1H0v9.69l-.06.06.06.06z",
16
+ fill: "currentColor",
17
+ fillRule: "evenodd"
18
+ })
19
+ });
20
+
21
+ //# sourceMappingURL=ImageIcon.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../src/components/icons/ImageIcon.tsx"],"sourcesContent":["import React from 'react'\n\nexport const ImageIcon: React.FC<React.SVGProps<SVGSVGElement>> = (props) => (\n <svg\n data-testid=\"geist-icon\"\n height=\"16\"\n strokeLinejoin=\"round\"\n style={{ color: 'currentcolor' }}\n viewBox=\"0 0 16 16\"\n width=\"16\"\n {...props}\n >\n <path\n clipRule=\"evenodd\"\n d=\"M14.5 2.5h-13v6.69l1.47-1.47.22-.22h3.75l.03-.03 3.5-3.5h1.06l2.97 2.97V2.5zM8 8.56l1.53 1.53.53.53L9 11.68l-.53-.53L6.32 9H3.81l-2.28 2.28-.03.03v1.19a1 1 0 001 1h11a1 1 0 001-1V9.06L11 5.56 8.03 8.53 8 8.56zm-8 2.25v1.69A2.5 2.5 0 002.5 15h11a2.5 2.5 0 002.5-2.5V9.56l.56-.56-.53-.53-.03-.03V1H0v9.69l-.06.06.06.06z\"\n fill=\"currentColor\"\n fillRule=\"evenodd\"\n />\n </svg>\n)\n"],"names":["React","ImageIcon","props","svg","data-testid","height","strokeLinejoin","style","color","viewBox","width","path","clipRule","d","fill","fillRule"],"mappings":";AAAA,OAAOA,WAAW,QAAO;AAEzB,OAAO,MAAMC,YAAqD,CAACC,sBACjE,KAACC;QACCC,eAAY;QACZC,QAAO;QACPC,gBAAe;QACfC,OAAO;YAAEC,OAAO;QAAe;QAC/BC,SAAQ;QACRC,OAAM;QACL,GAAGR,KAAK;kBAET,cAAA,KAACS;YACCC,UAAS;YACTC,GAAE;YACFC,MAAK;YACLC,UAAS;;OAGd"}
@@ -1,16 +1,20 @@
1
1
  import { jsx as _jsx } from "react/jsx-runtime";
2
2
  export function Lightning() {
3
3
  return /*#__PURE__*/ _jsx("svg", {
4
- fill: "currentColor",
4
+ "data-testid": "geist-icon",
5
+ height: "16",
6
+ strokeLinejoin: "round",
5
7
  style: {
8
+ color: 'currentcolor',
6
9
  height: '1rem',
7
10
  width: '1rem'
8
11
  },
9
- viewBox: "0 0 20 20",
10
- xmlns: "http://www.w3.org/2000/svg",
12
+ viewBox: "0 0 16 16",
13
+ width: "16",
11
14
  children: /*#__PURE__*/ _jsx("path", {
12
15
  clipRule: "evenodd",
13
- d: "M11.3 1.046A1 1 0 0112 2v5h4a1 1 0 01.82 1.573l-7 10A1 1 0 018 18v-5H4a1 1 0 01-.82-1.573l7-10a1 1 0 011.12-.38z",
16
+ d: "M7.157 0L2.333 9.408l-.56 1.092H7a.25.25 0 01.25.25V16h1.593l4.824-9.408.56-1.092H9a.25.25 0 01-.25-.25V0H7.157zM7 9H4.227L7.25 3.106V5.25C7.25 6.216 8.034 7 9 7h2.773L8.75 12.894V10.75A1.75 1.75 0 007 9z",
17
+ fill: "currentColor",
14
18
  fillRule: "evenodd"
15
19
  })
16
20
  });