@trackunit/react-compound-components 1.7.90 → 1.7.92
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.
- package/index.cjs.js +2 -138
- package/index.esm.js +6 -137
- package/package.json +11 -13
- package/src/ConfirmationDialog/ConfirmationDialogContextProvider.d.ts +2 -2
- package/src/ConfirmationDialog/ConfirmationDialogModal.d.ts +2 -1
- package/src/ConfirmationDialog/useConfirmationDialog.demo.d.ts +2 -1
- package/src/ConfirmationDialog/useConfirmationDialog.stories.d.ts +1 -1
- package/src/index.d.ts +0 -1
- package/src/translation.d.ts +4 -7
- package/src/ImageCollection/ImageCollection.d.ts +0 -31
- package/src/ImageCollection/ImageCollection.stories.d.ts +0 -39
- package/src/ImageCollection/helpers.d.ts +0 -13
- package/src/ImageCollection/index.d.ts +0 -2
package/index.cjs.js
CHANGED
|
@@ -6,11 +6,9 @@ var reactCoreHooks = require('@trackunit/react-core-hooks');
|
|
|
6
6
|
var reactModal = require('@trackunit/react-modal');
|
|
7
7
|
var react = require('react');
|
|
8
8
|
var reactComponents = require('@trackunit/react-components');
|
|
9
|
-
var cssClassVarianceUtilities = require('@trackunit/css-class-variance-utilities');
|
|
10
|
-
var ImageGallery = require('react-image-gallery');
|
|
11
|
-
var tailwindMerge = require('tailwind-merge');
|
|
12
|
-
var dateAndTimeUtils = require('@trackunit/date-and-time-utils');
|
|
13
9
|
var reactFormComponents = require('@trackunit/react-form-components');
|
|
10
|
+
var tailwindMerge = require('tailwind-merge');
|
|
11
|
+
var cssClassVarianceUtilities = require('@trackunit/css-class-variance-utilities');
|
|
14
12
|
|
|
15
13
|
var defaultTranslations = {
|
|
16
14
|
"confirmationDialog.default.message": "Are you certain that you wish to proceed with this action?",
|
|
@@ -121,135 +119,6 @@ const ConfirmationDialogContextProvider = ({ children }) => {
|
|
|
121
119
|
return (jsxRuntime.jsxs(reactCoreHooks.ConfirmationDialogProvider, { value: value, children: [children, resolveAction ? jsxRuntime.jsx(ConfirmationDialogModal, { ...modal, ...confirmationDialogModalProps }) : null] }));
|
|
122
120
|
};
|
|
123
121
|
|
|
124
|
-
const IMAGE_ENDPOINT = "https://images.iris.trackunit.com";
|
|
125
|
-
/**
|
|
126
|
-
* Generates an url for the original sized image from the image id
|
|
127
|
-
*/
|
|
128
|
-
const createOriginalUrl = (id) => `${IMAGE_ENDPOINT}/${btoa(JSON.stringify({
|
|
129
|
-
key: id,
|
|
130
|
-
}))}`;
|
|
131
|
-
const createResizedUrl = (id, width, height) => {
|
|
132
|
-
const request = {
|
|
133
|
-
key: id,
|
|
134
|
-
edits: {
|
|
135
|
-
resize: {
|
|
136
|
-
width,
|
|
137
|
-
height,
|
|
138
|
-
fit: "contain",
|
|
139
|
-
background: "transparent",
|
|
140
|
-
},
|
|
141
|
-
},
|
|
142
|
-
};
|
|
143
|
-
return `${IMAGE_ENDPOINT}/${btoa(JSON.stringify(request))}`;
|
|
144
|
-
};
|
|
145
|
-
/**
|
|
146
|
-
* Generates an url for the thumbnail size image
|
|
147
|
-
*/
|
|
148
|
-
const createThumbnailUrl = (id) => createResizedUrl(id, 100, 100);
|
|
149
|
-
/**
|
|
150
|
-
* Generates srcSet HTML attribute to avoid loading the full size image on small screens
|
|
151
|
-
*/
|
|
152
|
-
const createSrcSet = (id) => `${createResizedUrl(id, 480)} 480w, ${createResizedUrl(id, 800)} 800w`;
|
|
153
|
-
|
|
154
|
-
const ACCEPT_FOR_IMAGES = "image/jpeg, image/png, image/bmp, image/webp, image/gif";
|
|
155
|
-
const cvaGallery = cssClassVarianceUtilities.cvaMerge([
|
|
156
|
-
// These make the gallery grow to the height of the parent container,
|
|
157
|
-
// which avoids jumping of the thumbnail row when going through images
|
|
158
|
-
// with different ratios
|
|
159
|
-
"grow",
|
|
160
|
-
"[&_.image-gallery-content]:h-[100%]",
|
|
161
|
-
"[&_.image-gallery-content]:flex",
|
|
162
|
-
"[&_.image-gallery-content]:flex-col",
|
|
163
|
-
"[&_.image-gallery-slide-wrapper]:grow",
|
|
164
|
-
"[&_.image-gallery-slide-wrapper]:flex",
|
|
165
|
-
"[&_.image-gallery-slide-wrapper]:flex-col",
|
|
166
|
-
"[&_.image-gallery-slide-wrapper]:justify-center",
|
|
167
|
-
"[&_.image-gallery-slide]:flex",
|
|
168
|
-
"hover:[&_.image-gallery-icon]:text-blue-600",
|
|
169
|
-
// This centers thumbnails and makes the clickable area independent of image size
|
|
170
|
-
"[&_.image-gallery-thumbnail]:h-[100px]",
|
|
171
|
-
]);
|
|
172
|
-
const titleStyle = "absolute top-3 left-1/2 transform -translate-x-1/2 text-white bg-black/50 text-sm px-1 rounded-md backdrop-blur-sm text-wrap";
|
|
173
|
-
/**
|
|
174
|
-
* Show and manage images
|
|
175
|
-
*
|
|
176
|
-
* Will show thumbnail selection on desktop.
|
|
177
|
-
*
|
|
178
|
-
* Reduces bandwidth usage by lazy loading thumbnails and loading smaller versions of images depending on screen size.
|
|
179
|
-
*/
|
|
180
|
-
const ImageCollection = (props) => {
|
|
181
|
-
const { imagesData, actions, emptyPlaceholderActionLabel, additionalItemClassName, uploading } = props;
|
|
182
|
-
const [openImageId, setOpenImageId] = react.useState(imagesData[0]?.id);
|
|
183
|
-
const [isDeleting, setIsDeleting] = react.useState(false);
|
|
184
|
-
const { isLg } = reactComponents.useViewportBreakpoints();
|
|
185
|
-
const fileInputRef = react.useRef(null);
|
|
186
|
-
const imageGalleryRef = react.useRef(null);
|
|
187
|
-
const uploadButton = react.useMemo(() => actions?.upload ? (jsxRuntime.jsx("div", { className: "flex justify-end", children: jsxRuntime.jsx(reactComponents.Button, { loading: uploading, onClick: () => fileInputRef.current?.click(), children: actions.upload.label }) })) : null, [actions?.upload, uploading]);
|
|
188
|
-
const items = react.useMemo(() => imagesData.map(image => ({
|
|
189
|
-
id: image.id,
|
|
190
|
-
original: createOriginalUrl(image.id),
|
|
191
|
-
thumbnail: createThumbnailUrl(image.id),
|
|
192
|
-
srcSet: createSrcSet(image.id),
|
|
193
|
-
name: image.name,
|
|
194
|
-
timestamp: dateAndTimeUtils.formatDateUtil(new Date(image.timestamp), { dateFormat: "medium", timeFormat: "medium" }),
|
|
195
|
-
})), [imagesData]);
|
|
196
|
-
react.useEffect(() => {
|
|
197
|
-
if ((!openImageId || !imagesData.map(x => x.id).includes(openImageId)) && imagesData.length > 0) {
|
|
198
|
-
setOpenImageId(imagesData[0]?.id);
|
|
199
|
-
}
|
|
200
|
-
}, [imagesData, openImageId]);
|
|
201
|
-
const onRemove = react.useCallback(async () => {
|
|
202
|
-
if (!(actions?.remove?.onRemove && openImageId)) {
|
|
203
|
-
return;
|
|
204
|
-
}
|
|
205
|
-
try {
|
|
206
|
-
let nextIndex;
|
|
207
|
-
const indexToDelete = imagesData.map(x => x.id).indexOf(openImageId);
|
|
208
|
-
const deletingLastImage = indexToDelete === imagesData.length - 1;
|
|
209
|
-
if (imagesData.length === 1) {
|
|
210
|
-
nextIndex = undefined;
|
|
211
|
-
}
|
|
212
|
-
else if (deletingLastImage) {
|
|
213
|
-
nextIndex = indexToDelete - 1;
|
|
214
|
-
}
|
|
215
|
-
else {
|
|
216
|
-
// we set the index after the deletion, so the index will be the same
|
|
217
|
-
nextIndex = indexToDelete;
|
|
218
|
-
}
|
|
219
|
-
setIsDeleting(true);
|
|
220
|
-
await actions.remove.onRemove(openImageId);
|
|
221
|
-
if (nextIndex !== undefined) {
|
|
222
|
-
imageGalleryRef.current && nextIndex && imageGalleryRef.current.slideToIndex(nextIndex);
|
|
223
|
-
}
|
|
224
|
-
}
|
|
225
|
-
finally {
|
|
226
|
-
setIsDeleting(false);
|
|
227
|
-
}
|
|
228
|
-
}, [actions?.remove, imagesData, openImageId]);
|
|
229
|
-
return (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [imagesData.length > 0 ? (jsxRuntime.jsxs("div", { className: "flex h-[100vh] max-h-[100vh] flex-col", "data-testid": "image-collection", children: [jsxRuntime.jsx(ImageGallery, { additionalClass: cvaGallery(), items: items, onBeforeSlide: index => setOpenImageId(items[index]?.id),
|
|
230
|
-
// Library typing is wrong, this is fired when a gallery image is clicked (library typing says div)
|
|
231
|
-
onClick: e => window.open(e.target.src, "_blank"), ref: imageGalleryRef, renderItem: ({ original, srcSet,
|
|
232
|
-
// Typing of the library is not flexible enough to add id, which is only used for the unit tests
|
|
233
|
-
// @ts-ignore
|
|
234
|
-
id,
|
|
235
|
-
// @ts-ignore
|
|
236
|
-
name,
|
|
237
|
-
// @ts-ignore
|
|
238
|
-
timestamp, }) => (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsx("img", { alt: "full", className: tailwindMerge.twMerge(additionalItemClassName, "w-[100%]", "object-contain"), "data-testid": `image-${id}`, loading: "lazy", sizes: "(max-width: 480px) 480px, 800px", src: original, srcSet: srcSet }), jsxRuntime.jsx("div", { className: titleStyle, "data-testid": `image-title-${id}`, onClick: e => e.stopPropagation(), children: `${name} - ${timestamp}` })] })), renderThumbInner: ({ thumbnail,
|
|
239
|
-
// Typing of the library is not flexible enough to add id, which is only used for the unit tests
|
|
240
|
-
// @ts-ignore
|
|
241
|
-
id, }) => jsxRuntime.jsx("img", { alt: "thumbnail", "data-testid": `thumbnail-${id}`, loading: "lazy", src: thumbnail }), showFullscreenButton: false, showPlayButton: false, showThumbnails: isLg,
|
|
242
|
-
// reduce sliding around during deletion
|
|
243
|
-
slideDuration: isDeleting ? 0 : 200, ...props }), uploadButton, actions?.remove ? (jsxRuntime.jsx(reactComponents.Button, { className: "absolute right-2 top-2", loading: isDeleting, onClick: onRemove, prefix: jsxRuntime.jsx(reactComponents.Icon, { name: "Trash", size: "small" }), variant: "secondary-danger", children: actions.remove.label })) : null] })) : actions?.upload?.onUpload ? (uploading ? (jsxRuntime.jsx(reactComponents.Spinner, {})) : (jsxRuntime.jsx(reactFormComponents.DropZone, { accept: ACCEPT_FOR_IMAGES, className: "h-[98vh]", dataTestId: "site-images-dropzone", filesSelected: actions.upload.onUpload, label: emptyPlaceholderActionLabel, multiple: true }))) : null, jsxRuntime.jsx("input", {
|
|
244
|
-
// Users can still select other files on mobile devices
|
|
245
|
-
accept: ACCEPT_FOR_IMAGES, "data-testid": "site-images-input-files", hidden: true, multiple: true, onChange: async (e) => {
|
|
246
|
-
if (!(e.target.files && actions?.upload)) {
|
|
247
|
-
return;
|
|
248
|
-
}
|
|
249
|
-
await actions.upload.onUpload(e.target.files);
|
|
250
|
-
}, ref: fileInputRef, type: "file" })] }));
|
|
251
|
-
};
|
|
252
|
-
|
|
253
122
|
const cvaPreferenceCard = cssClassVarianceUtilities.cvaMerge(["rounded-lg", "border", "border-neutral-200", "bg-white", "w-full"], {
|
|
254
123
|
variants: {
|
|
255
124
|
disabled: {
|
|
@@ -376,9 +245,4 @@ const PreferenceCard = ({ title, description, icon, input, firstTag, secondTag,
|
|
|
376
245
|
setupLibraryTranslations();
|
|
377
246
|
|
|
378
247
|
exports.ConfirmationDialogContextProvider = ConfirmationDialogContextProvider;
|
|
379
|
-
exports.IMAGE_ENDPOINT = IMAGE_ENDPOINT;
|
|
380
|
-
exports.ImageCollection = ImageCollection;
|
|
381
248
|
exports.PreferenceCard = PreferenceCard;
|
|
382
|
-
exports.createOriginalUrl = createOriginalUrl;
|
|
383
|
-
exports.createSrcSet = createSrcSet;
|
|
384
|
-
exports.createThumbnailUrl = createThumbnailUrl;
|
package/index.esm.js
CHANGED
|
@@ -1,14 +1,12 @@
|
|
|
1
|
-
import { jsxs, jsx
|
|
1
|
+
import { jsxs, jsx } from 'react/jsx-runtime';
|
|
2
2
|
import { registerTranslations, useNamespaceTranslation } from '@trackunit/i18n-library-translation';
|
|
3
3
|
import { ConfirmationDialogProvider } from '@trackunit/react-core-hooks';
|
|
4
4
|
import { Modal, ModalHeader, ModalBody, ModalFooter, useModal } from '@trackunit/react-modal';
|
|
5
|
-
import { useState, useMemo, useCallback
|
|
6
|
-
import { Button,
|
|
7
|
-
import {
|
|
8
|
-
import ImageGallery from 'react-image-gallery';
|
|
5
|
+
import { useState, useMemo, useCallback } from 'react';
|
|
6
|
+
import { Button, Tooltip, SkeletonLines, Icon, Text, Tag } from '@trackunit/react-components';
|
|
7
|
+
import { Checkbox, RadioItem, ToggleSwitch } from '@trackunit/react-form-components';
|
|
9
8
|
import { twMerge } from 'tailwind-merge';
|
|
10
|
-
import {
|
|
11
|
-
import { DropZone, Checkbox, RadioItem, ToggleSwitch } from '@trackunit/react-form-components';
|
|
9
|
+
import { cvaMerge } from '@trackunit/css-class-variance-utilities';
|
|
12
10
|
|
|
13
11
|
var defaultTranslations = {
|
|
14
12
|
"confirmationDialog.default.message": "Are you certain that you wish to proceed with this action?",
|
|
@@ -119,135 +117,6 @@ const ConfirmationDialogContextProvider = ({ children }) => {
|
|
|
119
117
|
return (jsxs(ConfirmationDialogProvider, { value: value, children: [children, resolveAction ? jsx(ConfirmationDialogModal, { ...modal, ...confirmationDialogModalProps }) : null] }));
|
|
120
118
|
};
|
|
121
119
|
|
|
122
|
-
const IMAGE_ENDPOINT = "https://images.iris.trackunit.com";
|
|
123
|
-
/**
|
|
124
|
-
* Generates an url for the original sized image from the image id
|
|
125
|
-
*/
|
|
126
|
-
const createOriginalUrl = (id) => `${IMAGE_ENDPOINT}/${btoa(JSON.stringify({
|
|
127
|
-
key: id,
|
|
128
|
-
}))}`;
|
|
129
|
-
const createResizedUrl = (id, width, height) => {
|
|
130
|
-
const request = {
|
|
131
|
-
key: id,
|
|
132
|
-
edits: {
|
|
133
|
-
resize: {
|
|
134
|
-
width,
|
|
135
|
-
height,
|
|
136
|
-
fit: "contain",
|
|
137
|
-
background: "transparent",
|
|
138
|
-
},
|
|
139
|
-
},
|
|
140
|
-
};
|
|
141
|
-
return `${IMAGE_ENDPOINT}/${btoa(JSON.stringify(request))}`;
|
|
142
|
-
};
|
|
143
|
-
/**
|
|
144
|
-
* Generates an url for the thumbnail size image
|
|
145
|
-
*/
|
|
146
|
-
const createThumbnailUrl = (id) => createResizedUrl(id, 100, 100);
|
|
147
|
-
/**
|
|
148
|
-
* Generates srcSet HTML attribute to avoid loading the full size image on small screens
|
|
149
|
-
*/
|
|
150
|
-
const createSrcSet = (id) => `${createResizedUrl(id, 480)} 480w, ${createResizedUrl(id, 800)} 800w`;
|
|
151
|
-
|
|
152
|
-
const ACCEPT_FOR_IMAGES = "image/jpeg, image/png, image/bmp, image/webp, image/gif";
|
|
153
|
-
const cvaGallery = cvaMerge([
|
|
154
|
-
// These make the gallery grow to the height of the parent container,
|
|
155
|
-
// which avoids jumping of the thumbnail row when going through images
|
|
156
|
-
// with different ratios
|
|
157
|
-
"grow",
|
|
158
|
-
"[&_.image-gallery-content]:h-[100%]",
|
|
159
|
-
"[&_.image-gallery-content]:flex",
|
|
160
|
-
"[&_.image-gallery-content]:flex-col",
|
|
161
|
-
"[&_.image-gallery-slide-wrapper]:grow",
|
|
162
|
-
"[&_.image-gallery-slide-wrapper]:flex",
|
|
163
|
-
"[&_.image-gallery-slide-wrapper]:flex-col",
|
|
164
|
-
"[&_.image-gallery-slide-wrapper]:justify-center",
|
|
165
|
-
"[&_.image-gallery-slide]:flex",
|
|
166
|
-
"hover:[&_.image-gallery-icon]:text-blue-600",
|
|
167
|
-
// This centers thumbnails and makes the clickable area independent of image size
|
|
168
|
-
"[&_.image-gallery-thumbnail]:h-[100px]",
|
|
169
|
-
]);
|
|
170
|
-
const titleStyle = "absolute top-3 left-1/2 transform -translate-x-1/2 text-white bg-black/50 text-sm px-1 rounded-md backdrop-blur-sm text-wrap";
|
|
171
|
-
/**
|
|
172
|
-
* Show and manage images
|
|
173
|
-
*
|
|
174
|
-
* Will show thumbnail selection on desktop.
|
|
175
|
-
*
|
|
176
|
-
* Reduces bandwidth usage by lazy loading thumbnails and loading smaller versions of images depending on screen size.
|
|
177
|
-
*/
|
|
178
|
-
const ImageCollection = (props) => {
|
|
179
|
-
const { imagesData, actions, emptyPlaceholderActionLabel, additionalItemClassName, uploading } = props;
|
|
180
|
-
const [openImageId, setOpenImageId] = useState(imagesData[0]?.id);
|
|
181
|
-
const [isDeleting, setIsDeleting] = useState(false);
|
|
182
|
-
const { isLg } = useViewportBreakpoints();
|
|
183
|
-
const fileInputRef = useRef(null);
|
|
184
|
-
const imageGalleryRef = useRef(null);
|
|
185
|
-
const uploadButton = useMemo(() => actions?.upload ? (jsx("div", { className: "flex justify-end", children: jsx(Button, { loading: uploading, onClick: () => fileInputRef.current?.click(), children: actions.upload.label }) })) : null, [actions?.upload, uploading]);
|
|
186
|
-
const items = useMemo(() => imagesData.map(image => ({
|
|
187
|
-
id: image.id,
|
|
188
|
-
original: createOriginalUrl(image.id),
|
|
189
|
-
thumbnail: createThumbnailUrl(image.id),
|
|
190
|
-
srcSet: createSrcSet(image.id),
|
|
191
|
-
name: image.name,
|
|
192
|
-
timestamp: formatDateUtil(new Date(image.timestamp), { dateFormat: "medium", timeFormat: "medium" }),
|
|
193
|
-
})), [imagesData]);
|
|
194
|
-
useEffect(() => {
|
|
195
|
-
if ((!openImageId || !imagesData.map(x => x.id).includes(openImageId)) && imagesData.length > 0) {
|
|
196
|
-
setOpenImageId(imagesData[0]?.id);
|
|
197
|
-
}
|
|
198
|
-
}, [imagesData, openImageId]);
|
|
199
|
-
const onRemove = useCallback(async () => {
|
|
200
|
-
if (!(actions?.remove?.onRemove && openImageId)) {
|
|
201
|
-
return;
|
|
202
|
-
}
|
|
203
|
-
try {
|
|
204
|
-
let nextIndex;
|
|
205
|
-
const indexToDelete = imagesData.map(x => x.id).indexOf(openImageId);
|
|
206
|
-
const deletingLastImage = indexToDelete === imagesData.length - 1;
|
|
207
|
-
if (imagesData.length === 1) {
|
|
208
|
-
nextIndex = undefined;
|
|
209
|
-
}
|
|
210
|
-
else if (deletingLastImage) {
|
|
211
|
-
nextIndex = indexToDelete - 1;
|
|
212
|
-
}
|
|
213
|
-
else {
|
|
214
|
-
// we set the index after the deletion, so the index will be the same
|
|
215
|
-
nextIndex = indexToDelete;
|
|
216
|
-
}
|
|
217
|
-
setIsDeleting(true);
|
|
218
|
-
await actions.remove.onRemove(openImageId);
|
|
219
|
-
if (nextIndex !== undefined) {
|
|
220
|
-
imageGalleryRef.current && nextIndex && imageGalleryRef.current.slideToIndex(nextIndex);
|
|
221
|
-
}
|
|
222
|
-
}
|
|
223
|
-
finally {
|
|
224
|
-
setIsDeleting(false);
|
|
225
|
-
}
|
|
226
|
-
}, [actions?.remove, imagesData, openImageId]);
|
|
227
|
-
return (jsxs(Fragment, { children: [imagesData.length > 0 ? (jsxs("div", { className: "flex h-[100vh] max-h-[100vh] flex-col", "data-testid": "image-collection", children: [jsx(ImageGallery, { additionalClass: cvaGallery(), items: items, onBeforeSlide: index => setOpenImageId(items[index]?.id),
|
|
228
|
-
// Library typing is wrong, this is fired when a gallery image is clicked (library typing says div)
|
|
229
|
-
onClick: e => window.open(e.target.src, "_blank"), ref: imageGalleryRef, renderItem: ({ original, srcSet,
|
|
230
|
-
// Typing of the library is not flexible enough to add id, which is only used for the unit tests
|
|
231
|
-
// @ts-ignore
|
|
232
|
-
id,
|
|
233
|
-
// @ts-ignore
|
|
234
|
-
name,
|
|
235
|
-
// @ts-ignore
|
|
236
|
-
timestamp, }) => (jsxs(Fragment, { children: [jsx("img", { alt: "full", className: twMerge(additionalItemClassName, "w-[100%]", "object-contain"), "data-testid": `image-${id}`, loading: "lazy", sizes: "(max-width: 480px) 480px, 800px", src: original, srcSet: srcSet }), jsx("div", { className: titleStyle, "data-testid": `image-title-${id}`, onClick: e => e.stopPropagation(), children: `${name} - ${timestamp}` })] })), renderThumbInner: ({ thumbnail,
|
|
237
|
-
// Typing of the library is not flexible enough to add id, which is only used for the unit tests
|
|
238
|
-
// @ts-ignore
|
|
239
|
-
id, }) => jsx("img", { alt: "thumbnail", "data-testid": `thumbnail-${id}`, loading: "lazy", src: thumbnail }), showFullscreenButton: false, showPlayButton: false, showThumbnails: isLg,
|
|
240
|
-
// reduce sliding around during deletion
|
|
241
|
-
slideDuration: isDeleting ? 0 : 200, ...props }), uploadButton, actions?.remove ? (jsx(Button, { className: "absolute right-2 top-2", loading: isDeleting, onClick: onRemove, prefix: jsx(Icon, { name: "Trash", size: "small" }), variant: "secondary-danger", children: actions.remove.label })) : null] })) : actions?.upload?.onUpload ? (uploading ? (jsx(Spinner, {})) : (jsx(DropZone, { accept: ACCEPT_FOR_IMAGES, className: "h-[98vh]", dataTestId: "site-images-dropzone", filesSelected: actions.upload.onUpload, label: emptyPlaceholderActionLabel, multiple: true }))) : null, jsx("input", {
|
|
242
|
-
// Users can still select other files on mobile devices
|
|
243
|
-
accept: ACCEPT_FOR_IMAGES, "data-testid": "site-images-input-files", hidden: true, multiple: true, onChange: async (e) => {
|
|
244
|
-
if (!(e.target.files && actions?.upload)) {
|
|
245
|
-
return;
|
|
246
|
-
}
|
|
247
|
-
await actions.upload.onUpload(e.target.files);
|
|
248
|
-
}, ref: fileInputRef, type: "file" })] }));
|
|
249
|
-
};
|
|
250
|
-
|
|
251
120
|
const cvaPreferenceCard = cvaMerge(["rounded-lg", "border", "border-neutral-200", "bg-white", "w-full"], {
|
|
252
121
|
variants: {
|
|
253
122
|
disabled: {
|
|
@@ -373,4 +242,4 @@ const PreferenceCard = ({ title, description, icon, input, firstTag, secondTag,
|
|
|
373
242
|
*/
|
|
374
243
|
setupLibraryTranslations();
|
|
375
244
|
|
|
376
|
-
export { ConfirmationDialogContextProvider,
|
|
245
|
+
export { ConfirmationDialogContextProvider, PreferenceCard };
|
package/package.json
CHANGED
|
@@ -1,23 +1,21 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@trackunit/react-compound-components",
|
|
3
|
-
"version": "1.7.
|
|
3
|
+
"version": "1.7.92",
|
|
4
4
|
"repository": "https://github.com/Trackunit/manager",
|
|
5
5
|
"license": "SEE LICENSE IN LICENSE.txt",
|
|
6
6
|
"dependencies": {
|
|
7
7
|
"react": "19.0.0",
|
|
8
8
|
"tailwind-merge": "^2.0.0",
|
|
9
|
-
"react-
|
|
10
|
-
"@trackunit/react-core-
|
|
11
|
-
"@trackunit/react-
|
|
12
|
-
"@trackunit/react-
|
|
13
|
-
"@trackunit/
|
|
14
|
-
"@trackunit/
|
|
15
|
-
"@trackunit/
|
|
16
|
-
"@trackunit/react-
|
|
17
|
-
"@trackunit/
|
|
18
|
-
"@trackunit/
|
|
19
|
-
"@trackunit/shared-utils": "1.9.58",
|
|
20
|
-
"@trackunit/ui-icons": "1.7.59"
|
|
9
|
+
"@trackunit/react-core-contexts-api": "1.8.64",
|
|
10
|
+
"@trackunit/react-core-hooks": "1.7.68",
|
|
11
|
+
"@trackunit/react-components": "1.10.27",
|
|
12
|
+
"@trackunit/react-modal": "1.8.87",
|
|
13
|
+
"@trackunit/css-class-variance-utilities": "1.7.59",
|
|
14
|
+
"@trackunit/react-form-components": "1.8.91",
|
|
15
|
+
"@trackunit/i18n-library-translation": "1.7.71",
|
|
16
|
+
"@trackunit/react-test-setup": "1.4.59",
|
|
17
|
+
"@trackunit/shared-utils": "1.9.59",
|
|
18
|
+
"@trackunit/ui-icons": "1.7.60"
|
|
21
19
|
},
|
|
22
20
|
"engines": {
|
|
23
21
|
"node": ">=22.x",
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { ReactNode } from "react";
|
|
1
|
+
import { ReactElement, ReactNode } from "react";
|
|
2
2
|
export interface ConfirmationDialogProviderProps {
|
|
3
3
|
children: ReactNode;
|
|
4
4
|
}
|
|
@@ -7,4 +7,4 @@ export interface ConfirmationDialogProviderProps {
|
|
|
7
7
|
*
|
|
8
8
|
* Provides confirmation dialog context and manages modal state with Promise-based resolution
|
|
9
9
|
*/
|
|
10
|
-
export declare const ConfirmationDialogContextProvider: ({ children }: ConfirmationDialogProviderProps) =>
|
|
10
|
+
export declare const ConfirmationDialogContextProvider: ({ children }: ConfirmationDialogProviderProps) => ReactElement;
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { CommonProps } from "@trackunit/react-components";
|
|
2
2
|
import { UseModalReturnValue } from "@trackunit/react-modal";
|
|
3
|
+
import { ReactElement } from "react";
|
|
3
4
|
import { ConfirmationDialogProps } from "./useConfirmationDialog.demo";
|
|
4
5
|
export interface ConfirmationDialogModalProps extends Pick<ConfirmationDialogProps, "title" | "message" | "primaryActionLabel" | "secondaryActionLabel" | "primaryActionType">, UseModalReturnValue, CommonProps {
|
|
5
6
|
handlePrimaryActionClick: () => void;
|
|
@@ -8,4 +9,4 @@ export interface ConfirmationDialogModalProps extends Pick<ConfirmationDialogPro
|
|
|
8
9
|
/**
|
|
9
10
|
*
|
|
10
11
|
*/
|
|
11
|
-
export declare const ConfirmationDialogModal: ({ title, message, handlePrimaryActionClick, handleSecondaryActionClick, secondaryActionLabel, primaryActionType, primaryActionLabel, ...modalProps }: ConfirmationDialogModalProps) =>
|
|
12
|
+
export declare const ConfirmationDialogModal: ({ title, message, handlePrimaryActionClick, handleSecondaryActionClick, secondaryActionLabel, primaryActionType, primaryActionLabel, ...modalProps }: ConfirmationDialogModalProps) => ReactElement;
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { ConfirmationDialogProps as ConfirmationDialogPropsActual } from "@trackunit/react-core-contexts-api";
|
|
2
|
+
import { ReactElement } from "react";
|
|
2
3
|
export interface ConfirmationDialogProps extends ConfirmationDialogPropsActual {
|
|
3
4
|
/**
|
|
4
5
|
* The heading of the modal.
|
|
@@ -37,4 +38,4 @@ export interface ConfirmationDialogProps extends ConfirmationDialogPropsActual {
|
|
|
37
38
|
*
|
|
38
39
|
* **ATTENTION:** In the Manager and Iris Apps, this hook will "just work". If you are using the hook in a custom setup, you need to wrap your app in the ConfirmationDialogContextProvider.
|
|
39
40
|
*/
|
|
40
|
-
export declare const UseConfirmationDialogDemoComponent: (props: ConfirmationDialogProps) =>
|
|
41
|
+
export declare const UseConfirmationDialogDemoComponent: (props: ConfirmationDialogProps) => ReactElement;
|
|
@@ -3,7 +3,7 @@ import { ReactElement } from "react";
|
|
|
3
3
|
type Story = StoryObj<typeof meta>;
|
|
4
4
|
declare const meta: {
|
|
5
5
|
title: string;
|
|
6
|
-
component: (props: import("./useConfirmationDialog.demo").ConfirmationDialogProps) =>
|
|
6
|
+
component: (props: import("./useConfirmationDialog.demo").ConfirmationDialogProps) => ReactElement;
|
|
7
7
|
parameters: {
|
|
8
8
|
docs: {
|
|
9
9
|
source: {
|
package/src/index.d.ts
CHANGED
package/src/translation.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import { NamespaceTransProps, TransForLibs, TranslationResource } from "@trackunit/i18n-library-translation";
|
|
1
|
+
import { NamespaceTransProps, TransForLibs, TranslationResource, useNamespaceTranslation } from "@trackunit/i18n-library-translation";
|
|
2
|
+
import { ReactElement } from "react";
|
|
2
3
|
import defaultTranslations from "./locales/en/translation.json";
|
|
3
4
|
/** A type for all available translation keys in this library */
|
|
4
5
|
export type TranslationKeys = keyof typeof defaultTranslations;
|
|
@@ -14,11 +15,7 @@ export declare const translations: TranslationResource<TranslationKeys>;
|
|
|
14
15
|
/**
|
|
15
16
|
* Local useTranslation for this specific library
|
|
16
17
|
*/
|
|
17
|
-
export declare const useTranslation: () =>
|
|
18
|
-
t: TransForLibs<"confirmationDialog.default.message" | "confirmationDialog.default.primarybutton" | "confirmationDialog.default.secondarybutton" | "confirmationDialog.default.title">;
|
|
19
|
-
i18n: import("i18next").i18n;
|
|
20
|
-
ready: boolean;
|
|
21
|
-
};
|
|
18
|
+
export declare const useTranslation: () => ReturnType<typeof useNamespaceTranslation<TranslationKeys>>;
|
|
22
19
|
/**
|
|
23
20
|
* Type of the t function for the local useTranslation for this specific library
|
|
24
21
|
*/
|
|
@@ -26,7 +23,7 @@ export type TranslationFunction = TransForLibs<TranslationKeys>;
|
|
|
26
23
|
/**
|
|
27
24
|
* Trans for this specific library.
|
|
28
25
|
*/
|
|
29
|
-
export declare const Trans: (props: NamespaceTransProps<TranslationKeys>) =>
|
|
26
|
+
export declare const Trans: (props: NamespaceTransProps<TranslationKeys>) => ReactElement;
|
|
30
27
|
/**
|
|
31
28
|
* Registers the translations for this library
|
|
32
29
|
*/
|
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
import { ComponentProps } from "react";
|
|
2
|
-
import ImageGallery from "react-image-gallery";
|
|
3
|
-
type Props = Omit<ComponentProps<typeof ImageGallery>, "items"> & {
|
|
4
|
-
imagesData: Array<{
|
|
5
|
-
id: string;
|
|
6
|
-
name: string;
|
|
7
|
-
timestamp: string;
|
|
8
|
-
}>;
|
|
9
|
-
actions?: {
|
|
10
|
-
upload?: {
|
|
11
|
-
label: string;
|
|
12
|
-
onUpload: (pictures: FileList) => Promise<void>;
|
|
13
|
-
};
|
|
14
|
-
remove?: {
|
|
15
|
-
label: string;
|
|
16
|
-
onRemove?: (id: string) => Promise<void>;
|
|
17
|
-
};
|
|
18
|
-
};
|
|
19
|
-
emptyPlaceholderActionLabel?: string;
|
|
20
|
-
additionalItemClassName?: string;
|
|
21
|
-
uploading?: boolean;
|
|
22
|
-
};
|
|
23
|
-
/**
|
|
24
|
-
* Show and manage images
|
|
25
|
-
*
|
|
26
|
-
* Will show thumbnail selection on desktop.
|
|
27
|
-
*
|
|
28
|
-
* Reduces bandwidth usage by lazy loading thumbnails and loading smaller versions of images depending on screen size.
|
|
29
|
-
*/
|
|
30
|
-
export declare const ImageCollection: (props: Props) => import("react/jsx-runtime").JSX.Element;
|
|
31
|
-
export {};
|
|
@@ -1,39 +0,0 @@
|
|
|
1
|
-
import { StoryObj } from "@storybook/react-webpack5";
|
|
2
|
-
import { ReactElement } from "react";
|
|
3
|
-
type Story = StoryObj<typeof meta>;
|
|
4
|
-
declare const meta: {
|
|
5
|
-
title: string;
|
|
6
|
-
component: (props: Omit<import("react-image-gallery").ReactImageGalleryProps, "items"> & {
|
|
7
|
-
imagesData: Array<{
|
|
8
|
-
id: string;
|
|
9
|
-
name: string;
|
|
10
|
-
timestamp: string;
|
|
11
|
-
}>;
|
|
12
|
-
actions?: {
|
|
13
|
-
upload?: {
|
|
14
|
-
label: string;
|
|
15
|
-
onUpload: (pictures: FileList) => Promise<void>;
|
|
16
|
-
};
|
|
17
|
-
remove?: {
|
|
18
|
-
label: string;
|
|
19
|
-
onRemove?: (id: string) => Promise<void>;
|
|
20
|
-
};
|
|
21
|
-
};
|
|
22
|
-
emptyPlaceholderActionLabel?: string;
|
|
23
|
-
additionalItemClassName?: string;
|
|
24
|
-
uploading?: boolean;
|
|
25
|
-
}) => import("react/jsx-runtime").JSX.Element;
|
|
26
|
-
tags: string[];
|
|
27
|
-
parameters: {
|
|
28
|
-
docs: {
|
|
29
|
-
source: {
|
|
30
|
-
type: string;
|
|
31
|
-
excludeDecorators: boolean;
|
|
32
|
-
};
|
|
33
|
-
};
|
|
34
|
-
};
|
|
35
|
-
};
|
|
36
|
-
export default meta;
|
|
37
|
-
export declare const PackageName: () => ReactElement;
|
|
38
|
-
export declare const Default: Story;
|
|
39
|
-
export declare const EmptyState: Story;
|
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
export declare const IMAGE_ENDPOINT = "https://images.iris.trackunit.com";
|
|
2
|
-
/**
|
|
3
|
-
* Generates an url for the original sized image from the image id
|
|
4
|
-
*/
|
|
5
|
-
export declare const createOriginalUrl: (id: string) => string;
|
|
6
|
-
/**
|
|
7
|
-
* Generates an url for the thumbnail size image
|
|
8
|
-
*/
|
|
9
|
-
export declare const createThumbnailUrl: (id: string) => string;
|
|
10
|
-
/**
|
|
11
|
-
* Generates srcSet HTML attribute to avoid loading the full size image on small screens
|
|
12
|
-
*/
|
|
13
|
-
export declare const createSrcSet: (id: string) => string;
|