@nubitio/ui 0.5.15 → 0.5.16
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/dist/index.cjs +160 -11
- package/dist/index.d.cts +54 -1
- package/dist/index.d.mts +54 -1
- package/dist/index.mjs +160 -12
- package/dist/style.css +241 -0
- package/package.json +4 -1
package/dist/index.cjs
CHANGED
|
@@ -25,6 +25,7 @@ let react = require("react");
|
|
|
25
25
|
react = __toESM(react, 1);
|
|
26
26
|
let react_jsx_runtime = require("react/jsx-runtime");
|
|
27
27
|
let react_dom = require("react-dom");
|
|
28
|
+
let react_dropzone = require("react-dropzone");
|
|
28
29
|
//#region packages/ui/Avatar.tsx
|
|
29
30
|
/**
|
|
30
31
|
* 8 semantic hues aligned with the Fluent / @nubitio design palette.
|
|
@@ -83,13 +84,13 @@ const Avatar = ({ owner = "", size, variant = "md", shape = "circle", alt, class
|
|
|
83
84
|
};
|
|
84
85
|
//#endregion
|
|
85
86
|
//#region packages/ui/Button.tsx
|
|
86
|
-
const cx$
|
|
87
|
+
const cx$5 = (...values) => values.filter(Boolean).join(" ");
|
|
87
88
|
const Button = ({ variant = "secondary", size = "md", fullWidth = false, icon, loading = false, className, children, disabled, ...props }) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
|
|
88
89
|
...props,
|
|
89
90
|
type: props.type ?? "button",
|
|
90
91
|
disabled: disabled || loading,
|
|
91
92
|
"aria-busy": loading || void 0,
|
|
92
|
-
className: cx$
|
|
93
|
+
className: cx$5("nb-button", `nb-button--${variant}`, size === "sm" && "nb-button--sm", fullWidth && "nb-button--full", className),
|
|
93
94
|
children: [loading ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
94
95
|
className: "nb-button-spinner",
|
|
95
96
|
"aria-hidden": "true"
|
|
@@ -103,7 +104,7 @@ const IconButton = ({ icon, label, variant = "default", className, ...props }) =
|
|
|
103
104
|
type: props.type ?? "button",
|
|
104
105
|
"aria-label": props["aria-label"] ?? label,
|
|
105
106
|
title: props.title ?? label,
|
|
106
|
-
className: cx$
|
|
107
|
+
className: cx$5("nb-icon-button", variant === "danger" && "nb-icon-button--danger", className),
|
|
107
108
|
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("i", {
|
|
108
109
|
className: icon,
|
|
109
110
|
"aria-hidden": "true"
|
|
@@ -352,10 +353,10 @@ const Card = ({ title, description, children }) => {
|
|
|
352
353
|
};
|
|
353
354
|
//#endregion
|
|
354
355
|
//#region packages/ui/FormControls.tsx
|
|
355
|
-
const cx$
|
|
356
|
+
const cx$4 = (...values) => values.filter(Boolean).join(" ");
|
|
356
357
|
const FormField = ({ label, error, helpText, children, className, ...props }) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("label", {
|
|
357
358
|
...props,
|
|
358
|
-
className: cx$
|
|
359
|
+
className: cx$4("nb-form-field", !!error && "nb-form-field--error", className),
|
|
359
360
|
children: [
|
|
360
361
|
label && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
361
362
|
className: "nb-form-field__label",
|
|
@@ -376,14 +377,14 @@ const TextField = (0, react.forwardRef)(function TextField({ className, invalid,
|
|
|
376
377
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
|
|
377
378
|
...props,
|
|
378
379
|
ref,
|
|
379
|
-
className: cx$
|
|
380
|
+
className: cx$4("nb-input", invalid && "nb-input--invalid", className)
|
|
380
381
|
});
|
|
381
382
|
});
|
|
382
383
|
const SelectField = (0, react.forwardRef)(function SelectField({ className, invalid, children, ...props }, ref) {
|
|
383
384
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("select", {
|
|
384
385
|
...props,
|
|
385
386
|
ref,
|
|
386
|
-
className: cx$
|
|
387
|
+
className: cx$4("nb-input", "nb-select", invalid && "nb-input--invalid", className),
|
|
387
388
|
children
|
|
388
389
|
});
|
|
389
390
|
});
|
|
@@ -391,10 +392,151 @@ const TextAreaField = (0, react.forwardRef)(function TextAreaField({ className,
|
|
|
391
392
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("textarea", {
|
|
392
393
|
...props,
|
|
393
394
|
ref,
|
|
394
|
-
className: cx$
|
|
395
|
+
className: cx$4("nb-input", "nb-textarea", invalid && "nb-input--invalid", className)
|
|
395
396
|
});
|
|
396
397
|
});
|
|
397
398
|
//#endregion
|
|
399
|
+
//#region packages/ui/FileDropzone.tsx
|
|
400
|
+
function cx$3(...values) {
|
|
401
|
+
return values.filter(Boolean).join(" ");
|
|
402
|
+
}
|
|
403
|
+
function buildDropzoneAccept(accept) {
|
|
404
|
+
if (!accept || accept === "*/*" || accept === "*") return void 0;
|
|
405
|
+
if (accept === "image/*") return {
|
|
406
|
+
"image/png": [".png"],
|
|
407
|
+
"image/jpeg": [".jpg", ".jpeg"],
|
|
408
|
+
"image/webp": [".webp"],
|
|
409
|
+
"image/gif": [".gif"]
|
|
410
|
+
};
|
|
411
|
+
if (accept.includes(",")) return accept.split(",").reduce((acc, token) => {
|
|
412
|
+
const trimmed = token.trim();
|
|
413
|
+
if (!trimmed) return acc;
|
|
414
|
+
if (trimmed.startsWith(".")) {
|
|
415
|
+
acc["application/octet-stream"] = [...acc["application/octet-stream"] ?? [], trimmed];
|
|
416
|
+
return acc;
|
|
417
|
+
}
|
|
418
|
+
acc[trimmed] = [];
|
|
419
|
+
return acc;
|
|
420
|
+
}, {});
|
|
421
|
+
if (accept.startsWith(".")) return { "application/octet-stream": [accept] };
|
|
422
|
+
return { [accept]: [] };
|
|
423
|
+
}
|
|
424
|
+
function FileDropzone({ accept, value = null, image = false, disabled = false, readOnly = false, invalid = false, uploading = false, error = null, labels, inputId, inputLabel, className, onFileSelect, onClear }) {
|
|
425
|
+
const previewUrl = value?.previewUrl ?? null;
|
|
426
|
+
const fileName = value?.fileName ?? null;
|
|
427
|
+
const fileUrl = value?.fileUrl ?? null;
|
|
428
|
+
const hasContent = !!(previewUrl || fileName);
|
|
429
|
+
const isInteractive = !disabled && !readOnly;
|
|
430
|
+
const { getRootProps, getInputProps, isDragActive, open } = (0, react_dropzone.useDropzone)({
|
|
431
|
+
accept: buildDropzoneAccept(accept),
|
|
432
|
+
disabled: disabled || readOnly || uploading,
|
|
433
|
+
multiple: false,
|
|
434
|
+
noClick: hasContent,
|
|
435
|
+
noKeyboard: hasContent,
|
|
436
|
+
onDrop: (acceptedFiles) => {
|
|
437
|
+
const file = acceptedFiles[0];
|
|
438
|
+
if (file) onFileSelect(file);
|
|
439
|
+
}
|
|
440
|
+
});
|
|
441
|
+
const placeholderIcon = image ? "ph-image" : "ph-file-arrow-up";
|
|
442
|
+
const placeholderTitle = isDragActive ? labels?.dropPrompt ?? "Drop file here" : image ? labels?.imagePrompt ?? "Drop image here or click to browse" : labels?.prompt ?? "Drop file here or click to browse";
|
|
443
|
+
const placeholderHint = image ? labels?.imageHint ?? "PNG, JPG, WebP or GIF" : labels?.hint ?? "Select one file";
|
|
444
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
445
|
+
className: cx$3("nb-file-dropzone", image && "nb-file-dropzone--image", invalid && "nb-file-dropzone--invalid", className),
|
|
446
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
447
|
+
...getRootProps({ className: cx$3("nb-file-dropzone__zone", isDragActive && "nb-file-dropzone__zone--active", hasContent && "nb-file-dropzone__zone--filled", uploading && "nb-file-dropzone__zone--uploading", !isInteractive && "nb-file-dropzone__zone--disabled") }),
|
|
448
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", { ...getInputProps({
|
|
449
|
+
id: inputId,
|
|
450
|
+
"aria-label": inputLabel
|
|
451
|
+
}) }), hasContent ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [
|
|
452
|
+
previewUrl ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("img", {
|
|
453
|
+
className: "nb-file-dropzone__preview",
|
|
454
|
+
src: previewUrl,
|
|
455
|
+
alt: inputLabel ?? fileName ?? ""
|
|
456
|
+
}) : /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
457
|
+
className: "nb-file-dropzone__file",
|
|
458
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
459
|
+
className: "nb-file-dropzone__file-icon",
|
|
460
|
+
"aria-hidden": "true",
|
|
461
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("i", { className: "ph ph-file" })
|
|
462
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
463
|
+
className: "nb-file-dropzone__file-meta",
|
|
464
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
465
|
+
className: "nb-file-dropzone__file-name",
|
|
466
|
+
children: fileName
|
|
467
|
+
}), fileUrl && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("a", {
|
|
468
|
+
className: "nb-file-dropzone__file-link",
|
|
469
|
+
href: fileUrl,
|
|
470
|
+
target: "_blank",
|
|
471
|
+
rel: "noreferrer",
|
|
472
|
+
onClick: (event) => event.stopPropagation(),
|
|
473
|
+
children: labels?.open ?? "Open"
|
|
474
|
+
})]
|
|
475
|
+
})]
|
|
476
|
+
}),
|
|
477
|
+
uploading && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
478
|
+
className: "nb-file-dropzone__overlay",
|
|
479
|
+
"aria-live": "polite",
|
|
480
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
481
|
+
className: "nb-file-dropzone__spinner",
|
|
482
|
+
"aria-hidden": "true"
|
|
483
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: labels?.uploading ?? "Uploading..." })]
|
|
484
|
+
}),
|
|
485
|
+
isInteractive && !uploading && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
486
|
+
className: "nb-file-dropzone__actions",
|
|
487
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
|
|
488
|
+
type: "button",
|
|
489
|
+
className: "nb-file-dropzone__action",
|
|
490
|
+
onClick: (event) => {
|
|
491
|
+
event.stopPropagation();
|
|
492
|
+
open();
|
|
493
|
+
},
|
|
494
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("i", {
|
|
495
|
+
className: "ph ph-arrows-clockwise",
|
|
496
|
+
"aria-hidden": "true"
|
|
497
|
+
}), labels?.replace ?? "Replace"]
|
|
498
|
+
}), onClear && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
|
|
499
|
+
type: "button",
|
|
500
|
+
className: "nb-file-dropzone__action nb-file-dropzone__action--danger",
|
|
501
|
+
onClick: (event) => {
|
|
502
|
+
event.stopPropagation();
|
|
503
|
+
onClear();
|
|
504
|
+
},
|
|
505
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("i", {
|
|
506
|
+
className: "ph ph-trash",
|
|
507
|
+
"aria-hidden": "true"
|
|
508
|
+
}), labels?.remove ?? "Remove"]
|
|
509
|
+
})]
|
|
510
|
+
})
|
|
511
|
+
] }) : /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
512
|
+
className: "nb-file-dropzone__placeholder",
|
|
513
|
+
children: [
|
|
514
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
515
|
+
className: "nb-file-dropzone__icon",
|
|
516
|
+
"aria-hidden": "true",
|
|
517
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("i", { className: `ph ${placeholderIcon}` })
|
|
518
|
+
}),
|
|
519
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
520
|
+
className: "nb-file-dropzone__title",
|
|
521
|
+
children: placeholderTitle
|
|
522
|
+
}),
|
|
523
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
524
|
+
className: "nb-file-dropzone__hint",
|
|
525
|
+
children: placeholderHint
|
|
526
|
+
})
|
|
527
|
+
]
|
|
528
|
+
})]
|
|
529
|
+
}), error && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
|
|
530
|
+
className: "nb-file-dropzone__error",
|
|
531
|
+
role: "alert",
|
|
532
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("i", {
|
|
533
|
+
className: "ph ph-warning-circle",
|
|
534
|
+
"aria-hidden": "true"
|
|
535
|
+
}), error]
|
|
536
|
+
})]
|
|
537
|
+
});
|
|
538
|
+
}
|
|
539
|
+
//#endregion
|
|
398
540
|
//#region packages/ui/AppDropdown.tsx
|
|
399
541
|
function cx$2(...values) {
|
|
400
542
|
return values.filter(Boolean).join(" ");
|
|
@@ -2358,11 +2500,16 @@ const TimelineVariantContext = (0, react.createContext)("stepper");
|
|
|
2358
2500
|
function useTimelineVariant() {
|
|
2359
2501
|
return (0, react.useContext)(TimelineVariantContext);
|
|
2360
2502
|
}
|
|
2361
|
-
function TimelineMarker({ status, variant }) {
|
|
2503
|
+
function TimelineMarker({ status, variant, marker }) {
|
|
2362
2504
|
if (variant === "log") return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
2363
2505
|
className: "nb-timeline__marker nb-timeline__marker--dot",
|
|
2364
2506
|
"aria-hidden": "true"
|
|
2365
2507
|
});
|
|
2508
|
+
if (marker != null) return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
2509
|
+
className: `nb-timeline__marker nb-timeline__marker--${status} nb-timeline__marker--custom`,
|
|
2510
|
+
"aria-hidden": "true",
|
|
2511
|
+
children: marker
|
|
2512
|
+
});
|
|
2366
2513
|
if (status === "complete") return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
2367
2514
|
className: "nb-timeline__marker nb-timeline__marker--complete",
|
|
2368
2515
|
"aria-hidden": "true",
|
|
@@ -2382,7 +2529,7 @@ function TimelineMarker({ status, variant }) {
|
|
|
2382
2529
|
"aria-hidden": "true"
|
|
2383
2530
|
});
|
|
2384
2531
|
}
|
|
2385
|
-
function TimelineItem({ status, title, timestamp, dateTime, tone = "default", children, className }) {
|
|
2532
|
+
function TimelineItem({ status, title, marker, timestamp, dateTime, tone = "default", children, className }) {
|
|
2386
2533
|
const variant = useTimelineVariant();
|
|
2387
2534
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("li", {
|
|
2388
2535
|
className: [
|
|
@@ -2395,7 +2542,8 @@ function TimelineItem({ status, title, timestamp, dateTime, tone = "default", ch
|
|
|
2395
2542
|
className: "nb-timeline__marker-col",
|
|
2396
2543
|
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(TimelineMarker, {
|
|
2397
2544
|
status,
|
|
2398
|
-
variant
|
|
2545
|
+
variant,
|
|
2546
|
+
marker
|
|
2399
2547
|
})
|
|
2400
2548
|
}), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
2401
2549
|
className: "nb-timeline__content",
|
|
@@ -2463,6 +2611,7 @@ exports.Drawer = Drawer;
|
|
|
2463
2611
|
exports.EN_UI_STRINGS = EN_UI_STRINGS;
|
|
2464
2612
|
exports.ES_UI_STRINGS = ES_UI_STRINGS;
|
|
2465
2613
|
exports.EmptyState = EmptyState;
|
|
2614
|
+
exports.FileDropzone = FileDropzone;
|
|
2466
2615
|
exports.FormField = FormField;
|
|
2467
2616
|
exports.IconButton = IconButton;
|
|
2468
2617
|
exports.Popover = Popover;
|
package/dist/index.d.cts
CHANGED
|
@@ -204,6 +204,56 @@ interface TextAreaFieldProps extends TextareaHTMLAttributes<HTMLTextAreaElement>
|
|
|
204
204
|
}
|
|
205
205
|
declare const TextAreaField: import("react").ForwardRefExoticComponent<TextAreaFieldProps & import("react").RefAttributes<HTMLTextAreaElement>>;
|
|
206
206
|
//#endregion
|
|
207
|
+
//#region packages/ui/FileDropzone.d.ts
|
|
208
|
+
interface FileDropzoneValue {
|
|
209
|
+
fileName?: string | null;
|
|
210
|
+
fileUrl?: string | null;
|
|
211
|
+
previewUrl?: string | null;
|
|
212
|
+
}
|
|
213
|
+
interface FileDropzoneLabels {
|
|
214
|
+
prompt?: string;
|
|
215
|
+
imagePrompt?: string;
|
|
216
|
+
dropPrompt?: string;
|
|
217
|
+
hint?: string;
|
|
218
|
+
imageHint?: string;
|
|
219
|
+
uploading?: string;
|
|
220
|
+
replace?: string;
|
|
221
|
+
remove?: string;
|
|
222
|
+
open?: string;
|
|
223
|
+
}
|
|
224
|
+
interface FileDropzoneProps {
|
|
225
|
+
accept?: string | null;
|
|
226
|
+
value?: FileDropzoneValue | null;
|
|
227
|
+
image?: boolean;
|
|
228
|
+
disabled?: boolean;
|
|
229
|
+
readOnly?: boolean;
|
|
230
|
+
invalid?: boolean;
|
|
231
|
+
uploading?: boolean;
|
|
232
|
+
error?: string | null;
|
|
233
|
+
labels?: FileDropzoneLabels;
|
|
234
|
+
inputId?: string;
|
|
235
|
+
inputLabel?: string;
|
|
236
|
+
className?: string;
|
|
237
|
+
onFileSelect: (file: File) => void;
|
|
238
|
+
onClear?: () => void;
|
|
239
|
+
}
|
|
240
|
+
declare function FileDropzone({
|
|
241
|
+
accept,
|
|
242
|
+
value,
|
|
243
|
+
image,
|
|
244
|
+
disabled,
|
|
245
|
+
readOnly,
|
|
246
|
+
invalid,
|
|
247
|
+
uploading,
|
|
248
|
+
error,
|
|
249
|
+
labels,
|
|
250
|
+
inputId,
|
|
251
|
+
inputLabel,
|
|
252
|
+
className,
|
|
253
|
+
onFileSelect,
|
|
254
|
+
onClear
|
|
255
|
+
}: FileDropzoneProps): import("react").JSX.Element;
|
|
256
|
+
//#endregion
|
|
207
257
|
//#region packages/ui/AppDropdown.d.ts
|
|
208
258
|
interface AppDropdownOption {
|
|
209
259
|
value: string;
|
|
@@ -739,6 +789,8 @@ interface TimelineProps {
|
|
|
739
789
|
interface TimelineItemProps {
|
|
740
790
|
status: TimelineItemStatus;
|
|
741
791
|
title: ReactNode;
|
|
792
|
+
/** Custom stepper marker content, for example a step number. Ignored by the `log` variant. */
|
|
793
|
+
marker?: ReactNode;
|
|
742
794
|
timestamp?: ReactNode;
|
|
743
795
|
dateTime?: string;
|
|
744
796
|
/** Marker accent for the `log` variant. */
|
|
@@ -749,6 +801,7 @@ interface TimelineItemProps {
|
|
|
749
801
|
declare function TimelineItem({
|
|
750
802
|
status,
|
|
751
803
|
title,
|
|
804
|
+
marker,
|
|
752
805
|
timestamp,
|
|
753
806
|
dateTime,
|
|
754
807
|
tone,
|
|
@@ -826,4 +879,4 @@ interface UiStringsProviderProps {
|
|
|
826
879
|
declare const UiStringsProvider: React$1.FC<UiStringsProviderProps>;
|
|
827
880
|
declare const useUiStrings: () => UiStrings;
|
|
828
881
|
//#endregion
|
|
829
|
-
export { ACCENT_PRESETS, type AccentPreset, AppDialog, type AppDialogProps, AppDropdown, type AppDropdownOption, type AppDropdownProps, type AppDropdownVariant, AppToolbar, type AppToolbarProps, Avatar, type AvatarProps, type AvatarShape, type AvatarSize, Badge, type BadgeProps, type BadgeSize, type BadgeVariant, Button, type ButtonProps, type ButtonSize, type ButtonVariant, Card, type CardProps, Chip, type ChipProps, CollapsibleSection, type CollapsibleSectionProps, ConfirmDialog, type ConfirmDialogProps, ContextMenu, type ContextMenuItem, type ContextMenuProps, DatePicker, type DatePickerProps, DateRangePicker, type DateRangePickerProps, type Density, DensityContext, type DensityContextValue, DensityProvider, Drawer, type DrawerProps, type DrawerSide, EN_UI_STRINGS, ES_UI_STRINGS, EmptyState, type EmptyStateProps, FormField, type FormFieldProps, IconButton, type IconButtonProps, Popover, type PopoverAlign, type PopoverProps, SelectField, type SelectFieldProps, SettingsPanel, type SettingsPanelProps, Skeleton, type SkeletonProps, StatCard, type StatCardProps, TextAreaField, type TextAreaFieldProps, TextField, type TextFieldProps, type Theme, ThemeContext, type ThemeContextValue, type ThemeMode, ThemeProvider, type ThemeProviderProps, ThemeSwitcher, type ThemeSwitcherProps, Timeline, TimelineItem, type TimelineItemProps, type TimelineItemStatus, type TimelineItemTone, type TimelineOrientation, type TimelineProps, type TimelineVariant, Toggle, type ToggleProps, type UiStrings, UiStringsProvider, type UiStringsProviderProps, type UseFloatingPanelOptions, type UseFloatingPanelResult, getAvatarHue, getAvatarInitials, useAccentColor, useDensity, useFloatingPanel, useTheme, useUiStrings };
|
|
882
|
+
export { ACCENT_PRESETS, type AccentPreset, AppDialog, type AppDialogProps, AppDropdown, type AppDropdownOption, type AppDropdownProps, type AppDropdownVariant, AppToolbar, type AppToolbarProps, Avatar, type AvatarProps, type AvatarShape, type AvatarSize, Badge, type BadgeProps, type BadgeSize, type BadgeVariant, Button, type ButtonProps, type ButtonSize, type ButtonVariant, Card, type CardProps, Chip, type ChipProps, CollapsibleSection, type CollapsibleSectionProps, ConfirmDialog, type ConfirmDialogProps, ContextMenu, type ContextMenuItem, type ContextMenuProps, DatePicker, type DatePickerProps, DateRangePicker, type DateRangePickerProps, type Density, DensityContext, type DensityContextValue, DensityProvider, Drawer, type DrawerProps, type DrawerSide, EN_UI_STRINGS, ES_UI_STRINGS, EmptyState, type EmptyStateProps, FileDropzone, type FileDropzoneLabels, type FileDropzoneProps, type FileDropzoneValue, FormField, type FormFieldProps, IconButton, type IconButtonProps, Popover, type PopoverAlign, type PopoverProps, SelectField, type SelectFieldProps, SettingsPanel, type SettingsPanelProps, Skeleton, type SkeletonProps, StatCard, type StatCardProps, TextAreaField, type TextAreaFieldProps, TextField, type TextFieldProps, type Theme, ThemeContext, type ThemeContextValue, type ThemeMode, ThemeProvider, type ThemeProviderProps, ThemeSwitcher, type ThemeSwitcherProps, Timeline, TimelineItem, type TimelineItemProps, type TimelineItemStatus, type TimelineItemTone, type TimelineOrientation, type TimelineProps, type TimelineVariant, Toggle, type ToggleProps, type UiStrings, UiStringsProvider, type UiStringsProviderProps, type UseFloatingPanelOptions, type UseFloatingPanelResult, getAvatarHue, getAvatarInitials, useAccentColor, useDensity, useFloatingPanel, useTheme, useUiStrings };
|
package/dist/index.d.mts
CHANGED
|
@@ -204,6 +204,56 @@ interface TextAreaFieldProps extends TextareaHTMLAttributes<HTMLTextAreaElement>
|
|
|
204
204
|
}
|
|
205
205
|
declare const TextAreaField: import("react").ForwardRefExoticComponent<TextAreaFieldProps & import("react").RefAttributes<HTMLTextAreaElement>>;
|
|
206
206
|
//#endregion
|
|
207
|
+
//#region packages/ui/FileDropzone.d.ts
|
|
208
|
+
interface FileDropzoneValue {
|
|
209
|
+
fileName?: string | null;
|
|
210
|
+
fileUrl?: string | null;
|
|
211
|
+
previewUrl?: string | null;
|
|
212
|
+
}
|
|
213
|
+
interface FileDropzoneLabels {
|
|
214
|
+
prompt?: string;
|
|
215
|
+
imagePrompt?: string;
|
|
216
|
+
dropPrompt?: string;
|
|
217
|
+
hint?: string;
|
|
218
|
+
imageHint?: string;
|
|
219
|
+
uploading?: string;
|
|
220
|
+
replace?: string;
|
|
221
|
+
remove?: string;
|
|
222
|
+
open?: string;
|
|
223
|
+
}
|
|
224
|
+
interface FileDropzoneProps {
|
|
225
|
+
accept?: string | null;
|
|
226
|
+
value?: FileDropzoneValue | null;
|
|
227
|
+
image?: boolean;
|
|
228
|
+
disabled?: boolean;
|
|
229
|
+
readOnly?: boolean;
|
|
230
|
+
invalid?: boolean;
|
|
231
|
+
uploading?: boolean;
|
|
232
|
+
error?: string | null;
|
|
233
|
+
labels?: FileDropzoneLabels;
|
|
234
|
+
inputId?: string;
|
|
235
|
+
inputLabel?: string;
|
|
236
|
+
className?: string;
|
|
237
|
+
onFileSelect: (file: File) => void;
|
|
238
|
+
onClear?: () => void;
|
|
239
|
+
}
|
|
240
|
+
declare function FileDropzone({
|
|
241
|
+
accept,
|
|
242
|
+
value,
|
|
243
|
+
image,
|
|
244
|
+
disabled,
|
|
245
|
+
readOnly,
|
|
246
|
+
invalid,
|
|
247
|
+
uploading,
|
|
248
|
+
error,
|
|
249
|
+
labels,
|
|
250
|
+
inputId,
|
|
251
|
+
inputLabel,
|
|
252
|
+
className,
|
|
253
|
+
onFileSelect,
|
|
254
|
+
onClear
|
|
255
|
+
}: FileDropzoneProps): import("react").JSX.Element;
|
|
256
|
+
//#endregion
|
|
207
257
|
//#region packages/ui/AppDropdown.d.ts
|
|
208
258
|
interface AppDropdownOption {
|
|
209
259
|
value: string;
|
|
@@ -739,6 +789,8 @@ interface TimelineProps {
|
|
|
739
789
|
interface TimelineItemProps {
|
|
740
790
|
status: TimelineItemStatus;
|
|
741
791
|
title: ReactNode;
|
|
792
|
+
/** Custom stepper marker content, for example a step number. Ignored by the `log` variant. */
|
|
793
|
+
marker?: ReactNode;
|
|
742
794
|
timestamp?: ReactNode;
|
|
743
795
|
dateTime?: string;
|
|
744
796
|
/** Marker accent for the `log` variant. */
|
|
@@ -749,6 +801,7 @@ interface TimelineItemProps {
|
|
|
749
801
|
declare function TimelineItem({
|
|
750
802
|
status,
|
|
751
803
|
title,
|
|
804
|
+
marker,
|
|
752
805
|
timestamp,
|
|
753
806
|
dateTime,
|
|
754
807
|
tone,
|
|
@@ -826,4 +879,4 @@ interface UiStringsProviderProps {
|
|
|
826
879
|
declare const UiStringsProvider: React$1.FC<UiStringsProviderProps>;
|
|
827
880
|
declare const useUiStrings: () => UiStrings;
|
|
828
881
|
//#endregion
|
|
829
|
-
export { ACCENT_PRESETS, type AccentPreset, AppDialog, type AppDialogProps, AppDropdown, type AppDropdownOption, type AppDropdownProps, type AppDropdownVariant, AppToolbar, type AppToolbarProps, Avatar, type AvatarProps, type AvatarShape, type AvatarSize, Badge, type BadgeProps, type BadgeSize, type BadgeVariant, Button, type ButtonProps, type ButtonSize, type ButtonVariant, Card, type CardProps, Chip, type ChipProps, CollapsibleSection, type CollapsibleSectionProps, ConfirmDialog, type ConfirmDialogProps, ContextMenu, type ContextMenuItem, type ContextMenuProps, DatePicker, type DatePickerProps, DateRangePicker, type DateRangePickerProps, type Density, DensityContext, type DensityContextValue, DensityProvider, Drawer, type DrawerProps, type DrawerSide, EN_UI_STRINGS, ES_UI_STRINGS, EmptyState, type EmptyStateProps, FormField, type FormFieldProps, IconButton, type IconButtonProps, Popover, type PopoverAlign, type PopoverProps, SelectField, type SelectFieldProps, SettingsPanel, type SettingsPanelProps, Skeleton, type SkeletonProps, StatCard, type StatCardProps, TextAreaField, type TextAreaFieldProps, TextField, type TextFieldProps, type Theme, ThemeContext, type ThemeContextValue, type ThemeMode, ThemeProvider, type ThemeProviderProps, ThemeSwitcher, type ThemeSwitcherProps, Timeline, TimelineItem, type TimelineItemProps, type TimelineItemStatus, type TimelineItemTone, type TimelineOrientation, type TimelineProps, type TimelineVariant, Toggle, type ToggleProps, type UiStrings, UiStringsProvider, type UiStringsProviderProps, type UseFloatingPanelOptions, type UseFloatingPanelResult, getAvatarHue, getAvatarInitials, useAccentColor, useDensity, useFloatingPanel, useTheme, useUiStrings };
|
|
882
|
+
export { ACCENT_PRESETS, type AccentPreset, AppDialog, type AppDialogProps, AppDropdown, type AppDropdownOption, type AppDropdownProps, type AppDropdownVariant, AppToolbar, type AppToolbarProps, Avatar, type AvatarProps, type AvatarShape, type AvatarSize, Badge, type BadgeProps, type BadgeSize, type BadgeVariant, Button, type ButtonProps, type ButtonSize, type ButtonVariant, Card, type CardProps, Chip, type ChipProps, CollapsibleSection, type CollapsibleSectionProps, ConfirmDialog, type ConfirmDialogProps, ContextMenu, type ContextMenuItem, type ContextMenuProps, DatePicker, type DatePickerProps, DateRangePicker, type DateRangePickerProps, type Density, DensityContext, type DensityContextValue, DensityProvider, Drawer, type DrawerProps, type DrawerSide, EN_UI_STRINGS, ES_UI_STRINGS, EmptyState, type EmptyStateProps, FileDropzone, type FileDropzoneLabels, type FileDropzoneProps, type FileDropzoneValue, FormField, type FormFieldProps, IconButton, type IconButtonProps, Popover, type PopoverAlign, type PopoverProps, SelectField, type SelectFieldProps, SettingsPanel, type SettingsPanelProps, Skeleton, type SkeletonProps, StatCard, type StatCardProps, TextAreaField, type TextAreaFieldProps, TextField, type TextFieldProps, type Theme, ThemeContext, type ThemeContextValue, type ThemeMode, ThemeProvider, type ThemeProviderProps, ThemeSwitcher, type ThemeSwitcherProps, Timeline, TimelineItem, type TimelineItemProps, type TimelineItemStatus, type TimelineItemTone, type TimelineOrientation, type TimelineProps, type TimelineVariant, Toggle, type ToggleProps, type UiStrings, UiStringsProvider, type UiStringsProviderProps, type UseFloatingPanelOptions, type UseFloatingPanelResult, getAvatarHue, getAvatarInitials, useAccentColor, useDensity, useFloatingPanel, useTheme, useUiStrings };
|
package/dist/index.mjs
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import React, { createContext, forwardRef, useCallback, useContext, useEffect, useId, useLayoutEffect, useMemo, useRef, useState } from "react";
|
|
2
2
|
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
3
3
|
import { createPortal } from "react-dom";
|
|
4
|
+
import { useDropzone } from "react-dropzone";
|
|
4
5
|
//#region packages/ui/Avatar.tsx
|
|
5
6
|
/**
|
|
6
7
|
* 8 semantic hues aligned with the Fluent / @nubitio design palette.
|
|
@@ -59,13 +60,13 @@ const Avatar = ({ owner = "", size, variant = "md", shape = "circle", alt, class
|
|
|
59
60
|
};
|
|
60
61
|
//#endregion
|
|
61
62
|
//#region packages/ui/Button.tsx
|
|
62
|
-
const cx$
|
|
63
|
+
const cx$5 = (...values) => values.filter(Boolean).join(" ");
|
|
63
64
|
const Button = ({ variant = "secondary", size = "md", fullWidth = false, icon, loading = false, className, children, disabled, ...props }) => /* @__PURE__ */ jsxs("button", {
|
|
64
65
|
...props,
|
|
65
66
|
type: props.type ?? "button",
|
|
66
67
|
disabled: disabled || loading,
|
|
67
68
|
"aria-busy": loading || void 0,
|
|
68
|
-
className: cx$
|
|
69
|
+
className: cx$5("nb-button", `nb-button--${variant}`, size === "sm" && "nb-button--sm", fullWidth && "nb-button--full", className),
|
|
69
70
|
children: [loading ? /* @__PURE__ */ jsx("span", {
|
|
70
71
|
className: "nb-button-spinner",
|
|
71
72
|
"aria-hidden": "true"
|
|
@@ -79,7 +80,7 @@ const IconButton = ({ icon, label, variant = "default", className, ...props }) =
|
|
|
79
80
|
type: props.type ?? "button",
|
|
80
81
|
"aria-label": props["aria-label"] ?? label,
|
|
81
82
|
title: props.title ?? label,
|
|
82
|
-
className: cx$
|
|
83
|
+
className: cx$5("nb-icon-button", variant === "danger" && "nb-icon-button--danger", className),
|
|
83
84
|
children: /* @__PURE__ */ jsx("i", {
|
|
84
85
|
className: icon,
|
|
85
86
|
"aria-hidden": "true"
|
|
@@ -328,10 +329,10 @@ const Card = ({ title, description, children }) => {
|
|
|
328
329
|
};
|
|
329
330
|
//#endregion
|
|
330
331
|
//#region packages/ui/FormControls.tsx
|
|
331
|
-
const cx$
|
|
332
|
+
const cx$4 = (...values) => values.filter(Boolean).join(" ");
|
|
332
333
|
const FormField = ({ label, error, helpText, children, className, ...props }) => /* @__PURE__ */ jsxs("label", {
|
|
333
334
|
...props,
|
|
334
|
-
className: cx$
|
|
335
|
+
className: cx$4("nb-form-field", !!error && "nb-form-field--error", className),
|
|
335
336
|
children: [
|
|
336
337
|
label && /* @__PURE__ */ jsx("span", {
|
|
337
338
|
className: "nb-form-field__label",
|
|
@@ -352,14 +353,14 @@ const TextField = forwardRef(function TextField({ className, invalid, ...props }
|
|
|
352
353
|
return /* @__PURE__ */ jsx("input", {
|
|
353
354
|
...props,
|
|
354
355
|
ref,
|
|
355
|
-
className: cx$
|
|
356
|
+
className: cx$4("nb-input", invalid && "nb-input--invalid", className)
|
|
356
357
|
});
|
|
357
358
|
});
|
|
358
359
|
const SelectField = forwardRef(function SelectField({ className, invalid, children, ...props }, ref) {
|
|
359
360
|
return /* @__PURE__ */ jsx("select", {
|
|
360
361
|
...props,
|
|
361
362
|
ref,
|
|
362
|
-
className: cx$
|
|
363
|
+
className: cx$4("nb-input", "nb-select", invalid && "nb-input--invalid", className),
|
|
363
364
|
children
|
|
364
365
|
});
|
|
365
366
|
});
|
|
@@ -367,10 +368,151 @@ const TextAreaField = forwardRef(function TextAreaField({ className, invalid, ..
|
|
|
367
368
|
return /* @__PURE__ */ jsx("textarea", {
|
|
368
369
|
...props,
|
|
369
370
|
ref,
|
|
370
|
-
className: cx$
|
|
371
|
+
className: cx$4("nb-input", "nb-textarea", invalid && "nb-input--invalid", className)
|
|
371
372
|
});
|
|
372
373
|
});
|
|
373
374
|
//#endregion
|
|
375
|
+
//#region packages/ui/FileDropzone.tsx
|
|
376
|
+
function cx$3(...values) {
|
|
377
|
+
return values.filter(Boolean).join(" ");
|
|
378
|
+
}
|
|
379
|
+
function buildDropzoneAccept(accept) {
|
|
380
|
+
if (!accept || accept === "*/*" || accept === "*") return void 0;
|
|
381
|
+
if (accept === "image/*") return {
|
|
382
|
+
"image/png": [".png"],
|
|
383
|
+
"image/jpeg": [".jpg", ".jpeg"],
|
|
384
|
+
"image/webp": [".webp"],
|
|
385
|
+
"image/gif": [".gif"]
|
|
386
|
+
};
|
|
387
|
+
if (accept.includes(",")) return accept.split(",").reduce((acc, token) => {
|
|
388
|
+
const trimmed = token.trim();
|
|
389
|
+
if (!trimmed) return acc;
|
|
390
|
+
if (trimmed.startsWith(".")) {
|
|
391
|
+
acc["application/octet-stream"] = [...acc["application/octet-stream"] ?? [], trimmed];
|
|
392
|
+
return acc;
|
|
393
|
+
}
|
|
394
|
+
acc[trimmed] = [];
|
|
395
|
+
return acc;
|
|
396
|
+
}, {});
|
|
397
|
+
if (accept.startsWith(".")) return { "application/octet-stream": [accept] };
|
|
398
|
+
return { [accept]: [] };
|
|
399
|
+
}
|
|
400
|
+
function FileDropzone({ accept, value = null, image = false, disabled = false, readOnly = false, invalid = false, uploading = false, error = null, labels, inputId, inputLabel, className, onFileSelect, onClear }) {
|
|
401
|
+
const previewUrl = value?.previewUrl ?? null;
|
|
402
|
+
const fileName = value?.fileName ?? null;
|
|
403
|
+
const fileUrl = value?.fileUrl ?? null;
|
|
404
|
+
const hasContent = !!(previewUrl || fileName);
|
|
405
|
+
const isInteractive = !disabled && !readOnly;
|
|
406
|
+
const { getRootProps, getInputProps, isDragActive, open } = useDropzone({
|
|
407
|
+
accept: buildDropzoneAccept(accept),
|
|
408
|
+
disabled: disabled || readOnly || uploading,
|
|
409
|
+
multiple: false,
|
|
410
|
+
noClick: hasContent,
|
|
411
|
+
noKeyboard: hasContent,
|
|
412
|
+
onDrop: (acceptedFiles) => {
|
|
413
|
+
const file = acceptedFiles[0];
|
|
414
|
+
if (file) onFileSelect(file);
|
|
415
|
+
}
|
|
416
|
+
});
|
|
417
|
+
const placeholderIcon = image ? "ph-image" : "ph-file-arrow-up";
|
|
418
|
+
const placeholderTitle = isDragActive ? labels?.dropPrompt ?? "Drop file here" : image ? labels?.imagePrompt ?? "Drop image here or click to browse" : labels?.prompt ?? "Drop file here or click to browse";
|
|
419
|
+
const placeholderHint = image ? labels?.imageHint ?? "PNG, JPG, WebP or GIF" : labels?.hint ?? "Select one file";
|
|
420
|
+
return /* @__PURE__ */ jsxs("div", {
|
|
421
|
+
className: cx$3("nb-file-dropzone", image && "nb-file-dropzone--image", invalid && "nb-file-dropzone--invalid", className),
|
|
422
|
+
children: [/* @__PURE__ */ jsxs("div", {
|
|
423
|
+
...getRootProps({ className: cx$3("nb-file-dropzone__zone", isDragActive && "nb-file-dropzone__zone--active", hasContent && "nb-file-dropzone__zone--filled", uploading && "nb-file-dropzone__zone--uploading", !isInteractive && "nb-file-dropzone__zone--disabled") }),
|
|
424
|
+
children: [/* @__PURE__ */ jsx("input", { ...getInputProps({
|
|
425
|
+
id: inputId,
|
|
426
|
+
"aria-label": inputLabel
|
|
427
|
+
}) }), hasContent ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
428
|
+
previewUrl ? /* @__PURE__ */ jsx("img", {
|
|
429
|
+
className: "nb-file-dropzone__preview",
|
|
430
|
+
src: previewUrl,
|
|
431
|
+
alt: inputLabel ?? fileName ?? ""
|
|
432
|
+
}) : /* @__PURE__ */ jsxs("div", {
|
|
433
|
+
className: "nb-file-dropzone__file",
|
|
434
|
+
children: [/* @__PURE__ */ jsx("span", {
|
|
435
|
+
className: "nb-file-dropzone__file-icon",
|
|
436
|
+
"aria-hidden": "true",
|
|
437
|
+
children: /* @__PURE__ */ jsx("i", { className: "ph ph-file" })
|
|
438
|
+
}), /* @__PURE__ */ jsxs("div", {
|
|
439
|
+
className: "nb-file-dropzone__file-meta",
|
|
440
|
+
children: [/* @__PURE__ */ jsx("span", {
|
|
441
|
+
className: "nb-file-dropzone__file-name",
|
|
442
|
+
children: fileName
|
|
443
|
+
}), fileUrl && /* @__PURE__ */ jsx("a", {
|
|
444
|
+
className: "nb-file-dropzone__file-link",
|
|
445
|
+
href: fileUrl,
|
|
446
|
+
target: "_blank",
|
|
447
|
+
rel: "noreferrer",
|
|
448
|
+
onClick: (event) => event.stopPropagation(),
|
|
449
|
+
children: labels?.open ?? "Open"
|
|
450
|
+
})]
|
|
451
|
+
})]
|
|
452
|
+
}),
|
|
453
|
+
uploading && /* @__PURE__ */ jsxs("div", {
|
|
454
|
+
className: "nb-file-dropzone__overlay",
|
|
455
|
+
"aria-live": "polite",
|
|
456
|
+
children: [/* @__PURE__ */ jsx("span", {
|
|
457
|
+
className: "nb-file-dropzone__spinner",
|
|
458
|
+
"aria-hidden": "true"
|
|
459
|
+
}), /* @__PURE__ */ jsx("span", { children: labels?.uploading ?? "Uploading..." })]
|
|
460
|
+
}),
|
|
461
|
+
isInteractive && !uploading && /* @__PURE__ */ jsxs("div", {
|
|
462
|
+
className: "nb-file-dropzone__actions",
|
|
463
|
+
children: [/* @__PURE__ */ jsxs("button", {
|
|
464
|
+
type: "button",
|
|
465
|
+
className: "nb-file-dropzone__action",
|
|
466
|
+
onClick: (event) => {
|
|
467
|
+
event.stopPropagation();
|
|
468
|
+
open();
|
|
469
|
+
},
|
|
470
|
+
children: [/* @__PURE__ */ jsx("i", {
|
|
471
|
+
className: "ph ph-arrows-clockwise",
|
|
472
|
+
"aria-hidden": "true"
|
|
473
|
+
}), labels?.replace ?? "Replace"]
|
|
474
|
+
}), onClear && /* @__PURE__ */ jsxs("button", {
|
|
475
|
+
type: "button",
|
|
476
|
+
className: "nb-file-dropzone__action nb-file-dropzone__action--danger",
|
|
477
|
+
onClick: (event) => {
|
|
478
|
+
event.stopPropagation();
|
|
479
|
+
onClear();
|
|
480
|
+
},
|
|
481
|
+
children: [/* @__PURE__ */ jsx("i", {
|
|
482
|
+
className: "ph ph-trash",
|
|
483
|
+
"aria-hidden": "true"
|
|
484
|
+
}), labels?.remove ?? "Remove"]
|
|
485
|
+
})]
|
|
486
|
+
})
|
|
487
|
+
] }) : /* @__PURE__ */ jsxs("div", {
|
|
488
|
+
className: "nb-file-dropzone__placeholder",
|
|
489
|
+
children: [
|
|
490
|
+
/* @__PURE__ */ jsx("span", {
|
|
491
|
+
className: "nb-file-dropzone__icon",
|
|
492
|
+
"aria-hidden": "true",
|
|
493
|
+
children: /* @__PURE__ */ jsx("i", { className: `ph ${placeholderIcon}` })
|
|
494
|
+
}),
|
|
495
|
+
/* @__PURE__ */ jsx("span", {
|
|
496
|
+
className: "nb-file-dropzone__title",
|
|
497
|
+
children: placeholderTitle
|
|
498
|
+
}),
|
|
499
|
+
/* @__PURE__ */ jsx("span", {
|
|
500
|
+
className: "nb-file-dropzone__hint",
|
|
501
|
+
children: placeholderHint
|
|
502
|
+
})
|
|
503
|
+
]
|
|
504
|
+
})]
|
|
505
|
+
}), error && /* @__PURE__ */ jsxs("span", {
|
|
506
|
+
className: "nb-file-dropzone__error",
|
|
507
|
+
role: "alert",
|
|
508
|
+
children: [/* @__PURE__ */ jsx("i", {
|
|
509
|
+
className: "ph ph-warning-circle",
|
|
510
|
+
"aria-hidden": "true"
|
|
511
|
+
}), error]
|
|
512
|
+
})]
|
|
513
|
+
});
|
|
514
|
+
}
|
|
515
|
+
//#endregion
|
|
374
516
|
//#region packages/ui/AppDropdown.tsx
|
|
375
517
|
function cx$2(...values) {
|
|
376
518
|
return values.filter(Boolean).join(" ");
|
|
@@ -2334,11 +2476,16 @@ const TimelineVariantContext = createContext("stepper");
|
|
|
2334
2476
|
function useTimelineVariant() {
|
|
2335
2477
|
return useContext(TimelineVariantContext);
|
|
2336
2478
|
}
|
|
2337
|
-
function TimelineMarker({ status, variant }) {
|
|
2479
|
+
function TimelineMarker({ status, variant, marker }) {
|
|
2338
2480
|
if (variant === "log") return /* @__PURE__ */ jsx("span", {
|
|
2339
2481
|
className: "nb-timeline__marker nb-timeline__marker--dot",
|
|
2340
2482
|
"aria-hidden": "true"
|
|
2341
2483
|
});
|
|
2484
|
+
if (marker != null) return /* @__PURE__ */ jsx("span", {
|
|
2485
|
+
className: `nb-timeline__marker nb-timeline__marker--${status} nb-timeline__marker--custom`,
|
|
2486
|
+
"aria-hidden": "true",
|
|
2487
|
+
children: marker
|
|
2488
|
+
});
|
|
2342
2489
|
if (status === "complete") return /* @__PURE__ */ jsx("span", {
|
|
2343
2490
|
className: "nb-timeline__marker nb-timeline__marker--complete",
|
|
2344
2491
|
"aria-hidden": "true",
|
|
@@ -2358,7 +2505,7 @@ function TimelineMarker({ status, variant }) {
|
|
|
2358
2505
|
"aria-hidden": "true"
|
|
2359
2506
|
});
|
|
2360
2507
|
}
|
|
2361
|
-
function TimelineItem({ status, title, timestamp, dateTime, tone = "default", children, className }) {
|
|
2508
|
+
function TimelineItem({ status, title, marker, timestamp, dateTime, tone = "default", children, className }) {
|
|
2362
2509
|
const variant = useTimelineVariant();
|
|
2363
2510
|
return /* @__PURE__ */ jsxs("li", {
|
|
2364
2511
|
className: [
|
|
@@ -2371,7 +2518,8 @@ function TimelineItem({ status, title, timestamp, dateTime, tone = "default", ch
|
|
|
2371
2518
|
className: "nb-timeline__marker-col",
|
|
2372
2519
|
children: /* @__PURE__ */ jsx(TimelineMarker, {
|
|
2373
2520
|
status,
|
|
2374
|
-
variant
|
|
2521
|
+
variant,
|
|
2522
|
+
marker
|
|
2375
2523
|
})
|
|
2376
2524
|
}), /* @__PURE__ */ jsxs("div", {
|
|
2377
2525
|
className: "nb-timeline__content",
|
|
@@ -2419,4 +2567,4 @@ function Timeline({ variant = "stepper", orientation = "vertical", title, descri
|
|
|
2419
2567
|
});
|
|
2420
2568
|
}
|
|
2421
2569
|
//#endregion
|
|
2422
|
-
export { ACCENT_PRESETS, AppDialog, AppDropdown, AppToolbar, Avatar, Badge, Button, Card, Chip, CollapsibleSection, ConfirmDialog, ContextMenu, DatePicker, DateRangePicker, DensityContext, DensityProvider, Drawer, EN_UI_STRINGS, ES_UI_STRINGS, EmptyState, FormField, IconButton, Popover, SelectField, SettingsPanel, Skeleton, StatCard, TextAreaField, TextField, ThemeContext, ThemeProvider, ThemeSwitcher, Timeline, TimelineItem, Toggle, UiStringsProvider, getAvatarHue, getAvatarInitials, useAccentColor, useDensity, useFloatingPanel, useTheme, useUiStrings };
|
|
2570
|
+
export { ACCENT_PRESETS, AppDialog, AppDropdown, AppToolbar, Avatar, Badge, Button, Card, Chip, CollapsibleSection, ConfirmDialog, ContextMenu, DatePicker, DateRangePicker, DensityContext, DensityProvider, Drawer, EN_UI_STRINGS, ES_UI_STRINGS, EmptyState, FileDropzone, FormField, IconButton, Popover, SelectField, SettingsPanel, Skeleton, StatCard, TextAreaField, TextField, ThemeContext, ThemeProvider, ThemeSwitcher, Timeline, TimelineItem, Toggle, UiStringsProvider, getAvatarHue, getAvatarInitials, useAccentColor, useDensity, useFloatingPanel, useTheme, useUiStrings };
|
package/dist/style.css
CHANGED
|
@@ -753,6 +753,238 @@ html[data-density=compact] .nb-dialog__footer {
|
|
|
753
753
|
padding: var(--space-2) var(--space-3);
|
|
754
754
|
resize: vertical;
|
|
755
755
|
}
|
|
756
|
+
.nb-file-dropzone {
|
|
757
|
+
display: flex;
|
|
758
|
+
flex-direction: column;
|
|
759
|
+
gap: var(--space-1);
|
|
760
|
+
width: 100%;
|
|
761
|
+
}
|
|
762
|
+
|
|
763
|
+
.nb-file-dropzone__zone {
|
|
764
|
+
align-items: center;
|
|
765
|
+
background: var(--surface-1);
|
|
766
|
+
border: 1px dashed var(--border-color);
|
|
767
|
+
border-radius: var(--radius-lg);
|
|
768
|
+
box-sizing: border-box;
|
|
769
|
+
cursor: pointer;
|
|
770
|
+
display: flex;
|
|
771
|
+
justify-content: center;
|
|
772
|
+
min-height: 112px;
|
|
773
|
+
overflow: hidden;
|
|
774
|
+
position: relative;
|
|
775
|
+
transition: border-color var(--transition-base), background var(--transition-base), box-shadow var(--transition-base);
|
|
776
|
+
width: 100%;
|
|
777
|
+
}
|
|
778
|
+
.nb-file-dropzone__zone:hover:not(.nb-file-dropzone__zone--disabled):not(.nb-file-dropzone__zone--filled) {
|
|
779
|
+
background: color-mix(in srgb, var(--accent-color) 4%, var(--surface-1));
|
|
780
|
+
border-color: var(--accent-color);
|
|
781
|
+
}
|
|
782
|
+
.nb-file-dropzone__zone--active {
|
|
783
|
+
background: color-mix(in srgb, var(--accent-color) 8%, var(--surface-1));
|
|
784
|
+
border-color: var(--accent-color);
|
|
785
|
+
}
|
|
786
|
+
.nb-file-dropzone__zone--filled {
|
|
787
|
+
border-style: solid;
|
|
788
|
+
cursor: default;
|
|
789
|
+
min-height: 88px;
|
|
790
|
+
}
|
|
791
|
+
.nb-file-dropzone__zone--uploading {
|
|
792
|
+
pointer-events: none;
|
|
793
|
+
}
|
|
794
|
+
.nb-file-dropzone__zone--disabled {
|
|
795
|
+
cursor: not-allowed;
|
|
796
|
+
opacity: 0.72;
|
|
797
|
+
}
|
|
798
|
+
.nb-file-dropzone__zone:focus-visible {
|
|
799
|
+
box-shadow: 0 0 0 3px var(--focus-ring-color);
|
|
800
|
+
outline: none;
|
|
801
|
+
}
|
|
802
|
+
|
|
803
|
+
.nb-file-dropzone--image .nb-file-dropzone__zone {
|
|
804
|
+
min-height: 168px;
|
|
805
|
+
}
|
|
806
|
+
|
|
807
|
+
.nb-file-dropzone--image .nb-file-dropzone__zone--filled {
|
|
808
|
+
min-height: 180px;
|
|
809
|
+
}
|
|
810
|
+
|
|
811
|
+
.nb-file-dropzone--invalid .nb-file-dropzone__zone {
|
|
812
|
+
border-color: var(--error-color);
|
|
813
|
+
}
|
|
814
|
+
|
|
815
|
+
.nb-file-dropzone__placeholder {
|
|
816
|
+
align-items: center;
|
|
817
|
+
display: flex;
|
|
818
|
+
flex-direction: column;
|
|
819
|
+
gap: var(--space-2);
|
|
820
|
+
max-width: 320px;
|
|
821
|
+
padding: var(--space-4);
|
|
822
|
+
text-align: center;
|
|
823
|
+
}
|
|
824
|
+
|
|
825
|
+
.nb-file-dropzone__icon {
|
|
826
|
+
align-items: center;
|
|
827
|
+
background: color-mix(in srgb, var(--accent-color) 10%, transparent);
|
|
828
|
+
border-radius: 999px;
|
|
829
|
+
color: var(--accent-color);
|
|
830
|
+
display: inline-flex;
|
|
831
|
+
font-size: 24px;
|
|
832
|
+
height: 48px;
|
|
833
|
+
justify-content: center;
|
|
834
|
+
width: 48px;
|
|
835
|
+
}
|
|
836
|
+
|
|
837
|
+
.nb-file-dropzone__title {
|
|
838
|
+
color: var(--text-primary);
|
|
839
|
+
font-size: var(--font-size-sm);
|
|
840
|
+
font-weight: var(--font-weight-semibold);
|
|
841
|
+
}
|
|
842
|
+
|
|
843
|
+
.nb-file-dropzone__hint {
|
|
844
|
+
color: var(--text-tertiary);
|
|
845
|
+
font-size: var(--font-size-xs);
|
|
846
|
+
line-height: var(--line-height-tight);
|
|
847
|
+
}
|
|
848
|
+
|
|
849
|
+
.nb-file-dropzone__preview {
|
|
850
|
+
display: block;
|
|
851
|
+
height: 100%;
|
|
852
|
+
max-height: 220px;
|
|
853
|
+
object-fit: contain;
|
|
854
|
+
width: 100%;
|
|
855
|
+
}
|
|
856
|
+
|
|
857
|
+
.nb-file-dropzone__file {
|
|
858
|
+
align-items: center;
|
|
859
|
+
display: flex;
|
|
860
|
+
gap: var(--space-3);
|
|
861
|
+
max-width: 100%;
|
|
862
|
+
padding: var(--space-3) var(--space-4);
|
|
863
|
+
width: 100%;
|
|
864
|
+
}
|
|
865
|
+
|
|
866
|
+
.nb-file-dropzone__file-icon {
|
|
867
|
+
align-items: center;
|
|
868
|
+
background: var(--surface-0);
|
|
869
|
+
border: 1px solid var(--border-subtle);
|
|
870
|
+
border-radius: var(--radius-md);
|
|
871
|
+
color: var(--accent-color);
|
|
872
|
+
display: inline-flex;
|
|
873
|
+
flex: 0 0 auto;
|
|
874
|
+
font-size: 22px;
|
|
875
|
+
height: 44px;
|
|
876
|
+
justify-content: center;
|
|
877
|
+
width: 44px;
|
|
878
|
+
}
|
|
879
|
+
|
|
880
|
+
.nb-file-dropzone__file-meta {
|
|
881
|
+
display: flex;
|
|
882
|
+
flex: 1 1 auto;
|
|
883
|
+
flex-direction: column;
|
|
884
|
+
gap: 2px;
|
|
885
|
+
min-width: 0;
|
|
886
|
+
}
|
|
887
|
+
|
|
888
|
+
.nb-file-dropzone__file-name {
|
|
889
|
+
color: var(--text-primary);
|
|
890
|
+
font-size: var(--font-size-sm);
|
|
891
|
+
font-weight: var(--font-weight-medium);
|
|
892
|
+
overflow: hidden;
|
|
893
|
+
text-overflow: ellipsis;
|
|
894
|
+
white-space: nowrap;
|
|
895
|
+
}
|
|
896
|
+
|
|
897
|
+
.nb-file-dropzone__file-link {
|
|
898
|
+
color: var(--accent-color);
|
|
899
|
+
font-size: var(--font-size-xs);
|
|
900
|
+
text-decoration: none;
|
|
901
|
+
}
|
|
902
|
+
.nb-file-dropzone__file-link:hover {
|
|
903
|
+
text-decoration: underline;
|
|
904
|
+
}
|
|
905
|
+
|
|
906
|
+
.nb-file-dropzone__overlay {
|
|
907
|
+
align-items: center;
|
|
908
|
+
background: rgba(0, 0, 0, 0.42);
|
|
909
|
+
color: #fff;
|
|
910
|
+
display: flex;
|
|
911
|
+
flex-direction: column;
|
|
912
|
+
font-size: var(--font-size-sm);
|
|
913
|
+
gap: var(--space-2);
|
|
914
|
+
inset: 0;
|
|
915
|
+
justify-content: center;
|
|
916
|
+
position: absolute;
|
|
917
|
+
}
|
|
918
|
+
|
|
919
|
+
.nb-file-dropzone__spinner {
|
|
920
|
+
animation: nb-file-dropzone-spin 700ms linear infinite;
|
|
921
|
+
border: 2px solid rgba(255, 255, 255, 0.35);
|
|
922
|
+
border-radius: 999px;
|
|
923
|
+
border-top-color: #fff;
|
|
924
|
+
height: 24px;
|
|
925
|
+
width: 24px;
|
|
926
|
+
}
|
|
927
|
+
|
|
928
|
+
@keyframes nb-file-dropzone-spin {
|
|
929
|
+
to {
|
|
930
|
+
transform: rotate(360deg);
|
|
931
|
+
}
|
|
932
|
+
}
|
|
933
|
+
.nb-file-dropzone__actions {
|
|
934
|
+
align-items: center;
|
|
935
|
+
background: linear-gradient(to top, rgba(0, 0, 0, 0.58), transparent);
|
|
936
|
+
bottom: 0;
|
|
937
|
+
display: flex;
|
|
938
|
+
gap: var(--space-2);
|
|
939
|
+
inset-inline: 0;
|
|
940
|
+
justify-content: center;
|
|
941
|
+
opacity: 0;
|
|
942
|
+
padding: var(--space-3);
|
|
943
|
+
position: absolute;
|
|
944
|
+
transition: opacity var(--transition-base);
|
|
945
|
+
}
|
|
946
|
+
|
|
947
|
+
.nb-file-dropzone__zone--filled:hover .nb-file-dropzone__actions,
|
|
948
|
+
.nb-file-dropzone__zone--filled:focus-within .nb-file-dropzone__actions {
|
|
949
|
+
opacity: 1;
|
|
950
|
+
}
|
|
951
|
+
|
|
952
|
+
.nb-file-dropzone__action {
|
|
953
|
+
align-items: center;
|
|
954
|
+
background: var(--surface-1);
|
|
955
|
+
border: 1px solid var(--border-subtle);
|
|
956
|
+
border-radius: var(--radius-md);
|
|
957
|
+
color: var(--text-primary);
|
|
958
|
+
cursor: pointer;
|
|
959
|
+
display: inline-flex;
|
|
960
|
+
font: inherit;
|
|
961
|
+
font-size: var(--font-size-xs);
|
|
962
|
+
font-weight: var(--font-weight-medium);
|
|
963
|
+
gap: var(--space-1);
|
|
964
|
+
min-height: 28px;
|
|
965
|
+
padding: 0 var(--space-2);
|
|
966
|
+
transition: background var(--transition-base), border-color var(--transition-base), color var(--transition-base);
|
|
967
|
+
}
|
|
968
|
+
.nb-file-dropzone__action:hover {
|
|
969
|
+
border-color: var(--accent-color);
|
|
970
|
+
color: var(--accent-color);
|
|
971
|
+
}
|
|
972
|
+
.nb-file-dropzone__action--danger:hover {
|
|
973
|
+
border-color: var(--error-color);
|
|
974
|
+
color: var(--error-color);
|
|
975
|
+
}
|
|
976
|
+
.nb-file-dropzone__action:focus-visible {
|
|
977
|
+
box-shadow: 0 0 0 2px var(--focus-ring-color);
|
|
978
|
+
outline: none;
|
|
979
|
+
}
|
|
980
|
+
|
|
981
|
+
.nb-file-dropzone__error {
|
|
982
|
+
align-items: center;
|
|
983
|
+
color: var(--error-color);
|
|
984
|
+
display: inline-flex;
|
|
985
|
+
font-size: var(--font-size-xs);
|
|
986
|
+
gap: var(--space-1);
|
|
987
|
+
}
|
|
756
988
|
.nb-dropdown {
|
|
757
989
|
min-width: 0;
|
|
758
990
|
position: relative;
|
|
@@ -2827,6 +3059,15 @@ html[data-density=compact] .nb-drawer__footer {
|
|
|
2827
3059
|
width: 20px;
|
|
2828
3060
|
}
|
|
2829
3061
|
|
|
3062
|
+
.nb-timeline__marker--custom {
|
|
3063
|
+
font-size: var(--font-size-xs);
|
|
3064
|
+
font-weight: var(--font-weight-semibold);
|
|
3065
|
+
line-height: 1;
|
|
3066
|
+
}
|
|
3067
|
+
.nb-timeline__marker--custom.nb-timeline__marker--current::after {
|
|
3068
|
+
display: none;
|
|
3069
|
+
}
|
|
3070
|
+
|
|
2830
3071
|
.nb-timeline__marker--dot {
|
|
2831
3072
|
background: var(--surface-2);
|
|
2832
3073
|
border: 2px solid var(--accent-color);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nubitio/ui",
|
|
3
|
-
"version": "0.5.
|
|
3
|
+
"version": "0.5.16",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Visual primitives and theme system for the Nubit admin stack (dialogs, cards, toolbar, light/dark theme).",
|
|
6
6
|
"license": "MIT",
|
|
@@ -52,5 +52,8 @@
|
|
|
52
52
|
"peerDependencies": {
|
|
53
53
|
"react": "^19.0.0",
|
|
54
54
|
"react-dom": "^19.0.0"
|
|
55
|
+
},
|
|
56
|
+
"dependencies": {
|
|
57
|
+
"react-dropzone": "^15.0.0"
|
|
55
58
|
}
|
|
56
59
|
}
|