@alpaca-editor/sharedien-dam 1.0.4143

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.
@@ -0,0 +1,4 @@
1
+ import { config } from "@repo/eslint-config/react-internal";
2
+
3
+ /** @type {import("eslint").Linter.Config} */
4
+ export default config;
package/package.json ADDED
@@ -0,0 +1,35 @@
1
+ {
2
+ "name": "@alpaca-editor/sharedien-dam",
3
+ "version": "1.0.4143",
4
+ "type": "module",
5
+ "publishConfig": {
6
+ "access": "public"
7
+ },
8
+ "exports": {
9
+ ".": "./src/index.ts",
10
+ "./styles.css": "./styles.css"
11
+ },
12
+ "scripts": {
13
+ "build": "tsc -p tsconfig.build.json",
14
+ "lint": "eslint . --max-warnings 0",
15
+ "generate:component": "turbo gen react-component",
16
+ "check-types": "tsc --noEmit"
17
+ },
18
+ "devDependencies": {
19
+ "@repo/eslint-config": "*",
20
+ "@repo/typescript-config": "*",
21
+ "@turbo/gen": "^2.4.4",
22
+ "@types/node": "^22.13.9",
23
+ "@types/react": "19.0.10",
24
+ "@types/react-dom": "19.0.4",
25
+ "eslint": "^9.22.0",
26
+ "typescript": "5.8.2"
27
+ },
28
+ "dependencies": {
29
+ "@tailwindcss/postcss": "^4.0.14",
30
+ "postcss": "^8.5.3",
31
+ "react": "^19.0.0",
32
+ "react-dom": "^19.0.0",
33
+ "tailwindcss": "^4.0.14"
34
+ }
35
+ }
@@ -0,0 +1,524 @@
1
+ import { Button, DialogProps, Input, Select, TabView, TabPanel, Dialog, DialogContent, DialogHeader, DialogTitle, DialogFooter, useEditContext } from '@alpaca-editor/core';
2
+ import { useEffect, useState } from 'react';
3
+ import { DamImageValue, DamSelectorProps, SharedienDamExtension } from './types';
4
+ import React from 'react';
5
+ import { ExternalLink, Search, Check, X } from "lucide-react";
6
+
7
+ // Update interfaces for the API response
8
+ interface Derivation {
9
+ AssetTypeIdentifier: string;
10
+ FileTypeIdentifier: string;
11
+ FileMimeType: string;
12
+ DerivationTypeIdentifier: string;
13
+ FileName: string;
14
+ FileEnding: string;
15
+ FileSize: number;
16
+ Uri: string;
17
+ DownloadUri: string;
18
+ Status: string;
19
+ }
20
+
21
+ interface DerivationItem {
22
+ Derivation: Derivation;
23
+ IsPreferred: boolean;
24
+ IsPreview: boolean;
25
+ }
26
+
27
+ interface AssetProperty {
28
+ FieldName: string;
29
+ Value: string;
30
+ }
31
+
32
+ interface AssetInfo {
33
+ MeetsRestrictions: boolean;
34
+ Message: string;
35
+ }
36
+
37
+ interface AssetWarning {
38
+ ShouldWarn: boolean;
39
+ Message: string;
40
+ }
41
+
42
+ interface AssetResponse {
43
+ Derivations: DerivationItem[];
44
+ PreviewDerivationSrc: string;
45
+ AssetInfo: AssetInfo;
46
+ AssetWarning: AssetWarning;
47
+ AssetProperties: AssetProperty[];
48
+ }
49
+
50
+ interface Response {
51
+ Success: boolean
52
+ Message: string;
53
+ }
54
+
55
+ // Add this interface to declare the global sharedienAssetBrowser object
56
+ declare global {
57
+ interface Window {
58
+ sharedienAssetBrowser?: {
59
+ show: (url: string, config: any, callback: (content: any, isCancelled: boolean) => void, selector: string) => void;
60
+ }
61
+ }
62
+ }
63
+
64
+ // Utility function to format file sizes
65
+ function formatFileSize(bytes: number): string {
66
+ if (bytes === 0) return '0 Bytes';
67
+
68
+ const k = 1024;
69
+ const sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB'];
70
+ const i = Math.floor(Math.log(bytes) / Math.log(k));
71
+
72
+ return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i];
73
+ }
74
+
75
+ export function DamSelector({
76
+ onClose,
77
+ language = 'en',
78
+ }: DialogProps<DamImageValue> & DamSelectorProps) {
79
+ const [assetId, setAssetId] = useState('');
80
+ const [selectedDerivative, setSelectedDerivative] = useState<Derivation | null>(null);
81
+ const [assetData, setAssetData] = useState<AssetResponse | null>(null);
82
+ const [loading, setLoading] = useState(false);
83
+ const [error, setError] = useState<string | null>(null);
84
+ const [activeIndex, setActiveIndex] = useState(0);
85
+ const [isVisible, setIsVisible] = useState(false);
86
+ const [fromWidgetSelection, setFromWidgetSelection] = useState(false);
87
+
88
+ const editContext = useEditContext();
89
+ const sharedienDamConfig = editContext?.configuration?.extensions?.sharedienDam as SharedienDamExtension;
90
+ const damUrl = sharedienDamConfig?.damUrl ?? '';
91
+ const damScriptUrl = sharedienDamConfig?.damScriptUrl ?? '';
92
+
93
+ useEffect(() => {
94
+ const timer = setTimeout(() => {
95
+ setIsVisible(true);
96
+ }, 200);
97
+
98
+ return () => clearTimeout(timer);
99
+ }, []);
100
+
101
+ // Load the DAM widget script
102
+ useEffect(() => {
103
+ // Load the external script for the DAM widget
104
+ const script = document.createElement('script');
105
+ script.src = damScriptUrl;
106
+ script.async = true;
107
+ document.body.appendChild(script);
108
+
109
+ return () => {
110
+ // Clean up script when component unmounts
111
+ if (document.body.contains(script)) {
112
+ document.body.removeChild(script);
113
+ }
114
+ };
115
+ }, [damScriptUrl]);
116
+
117
+ // Initialize asset browser when switching to the second tab
118
+ useEffect(() => {
119
+ if (activeIndex === 1) {
120
+ initiateAssetBrowser();
121
+ }
122
+ }, [activeIndex]);
123
+
124
+ // Automatically search when assetId changes from widget selection
125
+ useEffect(() => {
126
+ if (assetId && assetId.trim() && fromWidgetSelection) {
127
+ searchAsset();
128
+ setFromWidgetSelection(false); // Reset the flag
129
+ }
130
+ }, [assetId, fromWidgetSelection]);
131
+
132
+ // Function to initialize the asset browser (converted from your C# code)
133
+ const initiateAssetBrowser = () => {
134
+ if (!window.sharedienAssetBrowser) {
135
+ console.error('DAM Asset Browser widget not loaded');
136
+ return;
137
+ }
138
+
139
+ const configuration = {
140
+ allowMultipleSelection: false,
141
+ canBeClosedByUser: false,
142
+ showMainNavigationBranding: false,
143
+ searchQuery: {
144
+ // Add your filters here if needed
145
+ }
146
+ };
147
+
148
+ const callback = (content: any, isCancelled: boolean) => {
149
+ if (isCancelled) {
150
+ console.log('Component has been cancelled');
151
+ } else {
152
+ console.log('Message received', content['selectedAssets'][0]);
153
+ // Set the asset ID and switch back to the first tab
154
+ if (content['selectedAssets'] && content['selectedAssets'][0]) {
155
+ setFromWidgetSelection(true); // Mark that this selection is from widget
156
+ setAssetId(content['selectedAssets'][0].identifier);
157
+ setActiveIndex(0); // Switch back to first tab
158
+ }
159
+ }
160
+ };
161
+
162
+ window.sharedienAssetBrowser.show(
163
+ damUrl,
164
+ configuration,
165
+ callback,
166
+ '#damBrowserContainer'
167
+ );
168
+ };
169
+
170
+ // Function to search for an asset
171
+ async function searchAsset(): Promise<void> {
172
+ if (!assetId.trim()) {
173
+ setError('Please enter an Asset ID');
174
+ return;
175
+ }
176
+
177
+ setLoading(true);
178
+ setError(null);
179
+
180
+ try {
181
+ // Call the API with assetId and language using POST
182
+ const response = await fetch('/alpaca/editor/sharedien', {
183
+ method: 'POST',
184
+ headers: {
185
+ 'Content-Type': 'application/json',
186
+ },
187
+ body: JSON.stringify({
188
+ assetId: assetId,
189
+ language: language
190
+ })
191
+ });
192
+
193
+ if (!response.ok) {
194
+ throw new Error(`Error fetching asset: ${response.statusText}`);
195
+ }
196
+
197
+ const data: AssetResponse & Response = await response.json();
198
+
199
+ if (data.Success === false) {
200
+ // Show the error message
201
+ setError(data.Message || 'An error occurred during insert');
202
+ return; // Don't close the dialog
203
+ }
204
+
205
+ setAssetData(data);
206
+
207
+ // Set the preferred derivation as selected by default
208
+ const preferredItem = data.Derivations.find(item => item.IsPreferred);
209
+ if (preferredItem) {
210
+ setSelectedDerivative(preferredItem.Derivation);
211
+ }
212
+ } catch (err) {
213
+ setError(err instanceof Error ? err.message : 'An unknown error occurred');
214
+ console.error('Error fetching asset:', err);
215
+ } finally {
216
+ setLoading(false);
217
+ }
218
+ }
219
+
220
+ ////
221
+ // Create select options from derivatives data
222
+ const getSelectOptions = () => {
223
+ if (!assetData?.Derivations) return [];
224
+
225
+ return assetData.Derivations.map(item => ({
226
+ value: item.Derivation.FileName,
227
+ label: `${item.Derivation.DerivationTypeIdentifier} (${item.Derivation.FileTypeIdentifier}) - ${formatFileSize(item.Derivation.FileSize)}${item.IsPreferred ? ' [recommended version for import]' : ''}`,
228
+ disabled: false
229
+ }));
230
+ };
231
+
232
+ // Handle select change
233
+ const handleSelectChange = (value: string) => {
234
+ const selectedItem = assetData?.Derivations.find(item => item.Derivation.FileName === value);
235
+ if (selectedItem) {
236
+ setSelectedDerivative(selectedItem.Derivation);
237
+ }
238
+ };
239
+
240
+ const handleInsert = async () => {
241
+ // Only proceed if a derivative is selected
242
+ if (!selectedDerivative) {
243
+ return;
244
+ }
245
+
246
+ try {
247
+ // Set loading state if needed
248
+ setLoading(true);
249
+
250
+ // Send POST request to insert endpoint
251
+ const response = await fetch('/alpaca/editor/sharedien/insert', {
252
+ method: 'POST',
253
+ headers: {
254
+ 'Content-Type': 'application/json',
255
+ },
256
+ body: JSON.stringify({
257
+ assetId: assetId,
258
+ language: language,
259
+ derivation: {
260
+ assetTypeIdentifier: selectedDerivative.AssetTypeIdentifier,
261
+ fileTypeIdentifier: selectedDerivative.FileTypeIdentifier,
262
+ fileMimeType: selectedDerivative.FileMimeType,
263
+ derivationTypeIdentifier: selectedDerivative.DerivationTypeIdentifier,
264
+ fileName: selectedDerivative.FileName,
265
+ fileEnding: selectedDerivative.FileEnding,
266
+ fileSize: selectedDerivative.FileSize,
267
+ uri: selectedDerivative.Uri,
268
+ downloadUri: selectedDerivative.DownloadUri,
269
+ status: selectedDerivative.Status
270
+ }
271
+ })
272
+ });
273
+
274
+ if (!response.ok) {
275
+ throw new Error(`Error inserting asset: ${response.statusText}`);
276
+ }
277
+
278
+ // Parse the response
279
+ const result = await response.json();
280
+
281
+ // Check if the response indicates failure
282
+ if (result.Success === false) {
283
+ // Show the error message
284
+ setError(result.Message || 'An error occurred during insert');
285
+ return; // Don't close the dialog
286
+ }
287
+
288
+ // Check if this is a video asset by looking at Asset Type property
289
+ const assetTypeProperty = assetData?.AssetProperties?.find(prop => prop.FieldName === "Asset Type");
290
+ const isVideo = assetTypeProperty?.Value === "Movie";
291
+
292
+ const mediaItemId = result?.length > 0 ? result[0] : undefined;
293
+
294
+ // Close the dialog and return the selected derivative info
295
+ onClose({
296
+ mediaId: isVideo ? undefined : mediaItemId,
297
+ videoId: isVideo ? mediaItemId : undefined,
298
+ });
299
+
300
+ } catch (err) {
301
+ // Handle errors
302
+ setError(err instanceof Error ? err.message : 'An unknown error occurred during insert');
303
+ console.error('Error inserting asset:', err);
304
+ } finally {
305
+ // Reset loading state
306
+ setLoading(false);
307
+ }
308
+ };
309
+
310
+ const footer = (
311
+ <div className="flex gap-3 p-4">
312
+ <span title={!selectedDerivative
313
+ ? "Please select a derivative first"
314
+ : loading
315
+ ? "Processing..."
316
+ : assetData?.AssetInfo?.MeetsRestrictions === false
317
+ ? "Cannot insert: " + assetData.AssetInfo.Message
318
+ : !assetData
319
+ ? "Please search for an asset first"
320
+ : undefined}>
321
+ <Button
322
+ size="sm"
323
+ onClick={handleInsert}
324
+ disabled={!selectedDerivative || loading || (assetData?.AssetInfo?.MeetsRestrictions === false) || !assetData}
325
+ >
326
+ {loading ? (
327
+ <i className="pi pi-spin pi-spinner w-4 h-4" />
328
+ ) : (
329
+ <Check className="w-4 h-4" />
330
+ )}
331
+ Insert
332
+ </Button>
333
+ </span>
334
+ <Button
335
+ size="sm"
336
+ onClick={() => onClose(null)}
337
+ >
338
+ <X className="w-4 h-4" />
339
+ Cancel
340
+ </Button>
341
+ </div>
342
+ );
343
+
344
+ return (
345
+ <Dialog open={true} onOpenChange={() => onClose(null)}>
346
+ <DialogContent
347
+ className="select-medidialog flex flex-col"
348
+ style={{ width: '90vw', height: '90vh', maxWidth: '90vw', maxHeight: '90vh' }}
349
+ >
350
+ <DialogHeader className="flex-shrink-0">
351
+ <DialogTitle>Get Asset from DAM</DialogTitle>
352
+ </DialogHeader>
353
+
354
+ <div className="flex-1 overflow-hidden flex flex-col">
355
+ <div className="p-3 flex-shrink-0">
356
+ <p className="p3 mb-4">
357
+ Browse for your asset in the DAM and copy the Asset ID. Paste the Asset ID below and click the Insert button to apply the image.
358
+ If available, you can also use the Asset Browser tab. In the widget, enter the Asset ID and click Confirm
359
+ </p>
360
+ </div>
361
+
362
+ {isVisible && (
363
+ <div className="flex-1 overflow-hidden">
364
+ <TabView
365
+ activeIndex={activeIndex}
366
+ onTabChange={(e) => setActiveIndex(e.index)}
367
+ className="dam-selector-tabs h-full"
368
+ >
369
+ <TabPanel header="SELECT BY ASSET ID">
370
+ <div className="h-full overflow-auto">
371
+ <div className="p-3 bg-blue-50 mb-4 flex align-items-center gap-2">
372
+ <i className="p-2 pi pi-info-circle" style={{ fontSize: '1.2rem' }} />
373
+ <span className="p-1 flex align-items-center">For testing you can open DAM Browser in a new Tab</span>
374
+ <Button
375
+ size="sm"
376
+ onClick={() => window.open(damUrl, '_blank')}>
377
+ <ExternalLink className="w-4 h-4" />
378
+ Open DAM
379
+ </Button>
380
+ </div>
381
+
382
+ <div className="grid grid-cols-2">
383
+ <div className="col-6 pr-4">
384
+ <div className="p-field mb-3">
385
+ <label htmlFor="assetId" className="block mb-2">Asset ID</label>
386
+ <Input
387
+ type="text"
388
+ id="assetId"
389
+ value={assetId}
390
+ onChange={(e) => setAssetId(e.target.value)}
391
+ className="w-full h-12 px-4"
392
+ placeholder="Enter Asset ID"
393
+ />
394
+ </div>
395
+
396
+ <Button
397
+ size="sm"
398
+ onClick={searchAsset}
399
+ disabled={loading}
400
+ >
401
+ <Search className="w-4 h-4" />
402
+ Search Asset
403
+ </Button>
404
+
405
+ {error && (
406
+ <div className="p-3 bg-red-50 text-red-700 mb-4 border-round">
407
+ <i className="pi pi-exclamation-circle mr-2" />
408
+ {error}
409
+ </div>
410
+ )}
411
+
412
+ {assetData && (
413
+ <div className="p-field p-card1 p-31">
414
+ <label htmlFor='derivative' className="block mb-2">Select Derivatives</label>
415
+ <div className="mb-4">
416
+ <Select
417
+ id="derivative"
418
+ value={selectedDerivative?.FileName || ''}
419
+ onValueChange={handleSelectChange}
420
+ options={getSelectOptions()}
421
+ placeholder="Choose a derivative..."
422
+ className="w-full h-12 px-4"
423
+ disabled={false}
424
+ />
425
+ </div>
426
+ </div>
427
+ )}
428
+ </div>
429
+
430
+ <div className="col-6 pl-4">
431
+ <div className="p-card p-3 flex flex-column grid grid-cols-1 grid-rows-2" style={{ minHeight: '300px' }}>
432
+ <div className="flex justify-content-center align-items-center row-1" style={{ flex: '1' }}>
433
+ {loading ? (
434
+ <i className="pi pi-spin pi-spinner text-6xl text-primary" />
435
+ ) : assetData?.PreviewDerivationSrc ? (
436
+ <img
437
+ src={assetData.PreviewDerivationSrc}
438
+ alt="Asset preview"
439
+ className="w-full h-auto max-h-64 object-contain border border-gray-200 rounded"
440
+ style={{ maxWidth: '100%' }}
441
+ />
442
+ ) : (
443
+ <div className="flex flex-column align-items-center justify-content-center h-full">
444
+ <i className="pi pi-image text-6xl text-gray-300 mb-3 p-1" />
445
+ <p className="text-gray-500 text-center">Asset preview will appear here</p>
446
+ </div>
447
+ )}
448
+ </div>
449
+
450
+ {assetData?.AssetInfo?.Message && (
451
+ <div className="mt-3 p-3 bg-red-50 border-round">
452
+ <i className="pi pi-info-circle mr-2 text-red-500"></i>
453
+ <span>{assetData.AssetInfo.Message}</span>
454
+ </div>
455
+ )}
456
+
457
+ {!assetData?.AssetInfo?.Message && assetData?.AssetWarning?.ShouldWarn && assetData.AssetWarning.Message && (
458
+ <div className="mt-3 p-3 bg-yellow-50 border-round">
459
+ <i className="pi pi-exclamation-triangle mr-2 text-yellow-500"></i>
460
+ <span>{assetData.AssetWarning.Message}</span>
461
+ </div>
462
+ )}
463
+
464
+ {assetData?.AssetProperties && assetData.AssetProperties.length > 0 && (
465
+ <div className="mt-3 p-3 bg-gray-50 border-round">
466
+ <div className="grid">
467
+ {assetData.AssetProperties.map((prop, index) => (
468
+ <React.Fragment key={index}>
469
+ <div className="col-4 font-bold">{prop.FieldName}:</div>
470
+ <div className="col-8">
471
+ {prop.FieldName === "File Size"
472
+ ? formatFileSize(parseInt(prop.Value))
473
+ : prop.FieldName === "Expiry Date"
474
+ ? new Date(prop.Value).toLocaleDateString()
475
+ : prop.Value}
476
+ </div>
477
+ </React.Fragment>
478
+ ))}
479
+ </div>
480
+ </div>
481
+ )}
482
+ </div>
483
+ </div>
484
+ </div>
485
+ </div>
486
+ </TabPanel>
487
+
488
+ <TabPanel header="BROWSE IN DAM">
489
+ <div className="h-full overflow-hidden">
490
+ <div className="h-full flex flex-col">
491
+ {/* Container for the DAM browser widget */}
492
+ <div id="damBrowserContainer" className="flex-1" style={{ minHeight: 0 }}>
493
+ {/* The widget will create its own iframe here */}
494
+ </div>
495
+
496
+ {/* Fallback iframe if the widget doesn't load */}
497
+ {!window.sharedienAssetBrowser && (
498
+ <iframe
499
+ src={damUrl}
500
+ className="w-full h-full border border-gray-300"
501
+ title="DAM Browser"
502
+ sandbox="allow-same-origin allow-scripts allow-popups allow-forms"
503
+ />
504
+ )}
505
+
506
+ <div className="mt-3 p-3 bg-yellow-50 border-round flex-shrink-0">
507
+ <i className="pi pi-exclamation-triangle mr-2 text-yellow-500"></i>
508
+ <span>Note: If the DAM widget doesn't load, you'll need to manually copy the Asset ID from the DAM and paste it in the Asset ID field on the first tab.</span>
509
+ </div>
510
+ </div>
511
+ </div>
512
+ </TabPanel>
513
+ </TabView>
514
+ </div>
515
+ )}
516
+ </div>
517
+
518
+ <DialogFooter className="flex-shrink-0 border-t bg-white relative z-10">
519
+ {footer}
520
+ </DialogFooter>
521
+ </DialogContent>
522
+ </Dialog>
523
+ );
524
+ }
@@ -0,0 +1,53 @@
1
+ import { ClientFieldButton, PictureRawValue } from "@alpaca-editor/core";
2
+ import { DamSelector } from "./DamSelector";
3
+ import { DamImageValue, DamSelectorProps } from "./types";
4
+
5
+ export const DamSelectorButton: ClientFieldButton = {
6
+ label: "Open sharedien DAM",
7
+ icon: "pi pi-external-link",
8
+ clientAction: async ({ editContext, field }) => {
9
+ const data = await editContext.openDialog<DamImageValue, DamSelectorProps>(DamSelector, {
10
+ language: field.descriptor.item.language
11
+ });
12
+
13
+ if (data?.mediaId || data?.videoId) {
14
+ const raw = (() => {
15
+ try {
16
+ return field?.rawValue && field?.rawValue[0] === "{"
17
+ ? (JSON.parse(field?.rawValue) as PictureRawValue)
18
+ : ({ Variants: [] } as PictureRawValue);
19
+ } catch (error) {
20
+ console.warn("Failed to parse picture field raw value:", error);
21
+ return { Variants: [] } as PictureRawValue;
22
+ }
23
+ })();
24
+
25
+ if (raw.Variants && raw.Variants.length > 0 && raw.Variants[0]?.Name) {
26
+ const variantName = raw.Variants[0].Name;
27
+ const selected = raw.Variants.find((x: any) => x.Name == variantName);
28
+ if (selected) {
29
+ selected.MediaId = data.mediaId;
30
+ selected.VideoId = data.videoId;
31
+ } else {
32
+ raw.Variants.push({
33
+ Name: variantName,
34
+ MediaId: data.mediaId,
35
+ VideoId: data.videoId,
36
+ });
37
+ }
38
+ } else {
39
+ console.warn("No existing variants with valid names found in picture field. Cannot determine variant name for DAM selection.");
40
+ return;
41
+ }
42
+
43
+ editContext!.operations.editField({
44
+ field: field.descriptor,
45
+ rawValue: JSON.stringify(raw),
46
+ refresh: "immediate",
47
+ });
48
+ }
49
+ },
50
+ isGenerator: false,
51
+ id: "open-sharedien-dam",
52
+ description: "Opens the sharedien DAM to select an image",
53
+ }
package/src/index.ts ADDED
@@ -0,0 +1,36 @@
1
+ import { EditorConfiguration } from "@alpaca-editor/core";
2
+ import { SharedienDamExtension, DamImageValue, DamSelectorProps } from "./types";
3
+ import { DamSelectorButton } from "./DamSelectorButton";
4
+ import { DamSelector } from "./DamSelector";
5
+
6
+ export function configureSharedienDam(
7
+ configuration: EditorConfiguration,
8
+ sharedienDam: SharedienDamExtension,
9
+ ) {
10
+ configuration.extensions = {
11
+ ...configuration.extensions,
12
+ sharedienDam: {
13
+ enableDamSelector: sharedienDam.enableDamSelector ?? false,
14
+ damUrl: sharedienDam.damUrl,
15
+ damScriptUrl: sharedienDam.damScriptUrl,
16
+ }
17
+ };
18
+
19
+ if (!configuration.fieldTypes.picture) {
20
+ configuration.fieldTypes.picture = {
21
+ editor: () => null,
22
+ buttons: []
23
+ }
24
+ }
25
+
26
+ if (!configuration.fieldTypes.picture.buttons) {
27
+ configuration.fieldTypes.picture.buttons = [];
28
+ }
29
+
30
+ //configuration.fieldTypes.picture.buttons.push(DamSelectorButton);
31
+
32
+ return configuration;
33
+ }
34
+
35
+ export { DamSelector, DamSelectorButton };
36
+ export type { DamImageValue, DamSelectorProps, SharedienDamExtension };
package/src/types.ts ADDED
@@ -0,0 +1,15 @@
1
+ export type DamSelectorProps = {
2
+ language?: string;
3
+ }
4
+
5
+ export type DamImageValue = {
6
+ mediaId: string | undefined;
7
+ videoId: string | undefined;
8
+ }
9
+
10
+ export type SharedienDamExtension = {
11
+ enableDamSelector?: boolean;
12
+ damUrl?: string;
13
+ damScriptUrl?: string;
14
+ }
15
+
package/styles.css ADDED
@@ -0,0 +1 @@
1
+ @source "./";
package/tsconfig.json ADDED
@@ -0,0 +1,9 @@
1
+ {
2
+ "extends": "@repo/typescript-config/react-library.json",
3
+ "compilerOptions": {
4
+ "jsx": "react",
5
+ "outDir": "dist"
6
+ },
7
+ "include": ["src"],
8
+ "exclude": ["node_modules", "dist"]
9
+ }