ssovee-os-web-ui 0.1.99 → 0.1.101
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/README.md +43 -0
- package/dist/index.cjs +65 -2
- package/dist/index.cjs.map +1 -1
- package/dist/index.css +25 -13
- package/dist/index.d.cts +8 -1
- package/dist/index.d.ts +8 -1
- package/dist/index.js +64 -3
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -84,6 +84,47 @@ Use `theme="vs-dark"` for a dark editor. The component also accepts Monaco `lang
|
|
|
84
84
|
|
|
85
85
|
The component supports `toolbar`, `plugins`, `fullWidth`, `error`, and `disabled` props for common form usage.
|
|
86
86
|
|
|
87
|
+
### RichEditor
|
|
88
|
+
|
|
89
|
+
`RichEditor` is a controlled rich-text editor that returns the edited content as HTML. Set `isDarkTheme` when the surrounding app uses the dark theme:
|
|
90
|
+
|
|
91
|
+
```tsx
|
|
92
|
+
import { useState } from "react";
|
|
93
|
+
import { RichEditor } from "ssovee-os-web-ui";
|
|
94
|
+
|
|
95
|
+
export function NoteEditor() {
|
|
96
|
+
const [content, setContent] = useState("<p>Write a note...</p>");
|
|
97
|
+
|
|
98
|
+
return (
|
|
99
|
+
<RichEditor
|
|
100
|
+
content={content}
|
|
101
|
+
onChange={setContent}
|
|
102
|
+
isDarkTheme
|
|
103
|
+
/>
|
|
104
|
+
);
|
|
105
|
+
}
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
### PreviewComponent
|
|
109
|
+
|
|
110
|
+
`PreviewComponent` previews a file from base64 data supplied by the host application. Pass either raw base64 or a complete data URL along with the original file name. Image files, PDFs, text files, and JSON are supported.
|
|
111
|
+
|
|
112
|
+
```tsx
|
|
113
|
+
import { PreviewComponent } from "ssovee-os-web-ui";
|
|
114
|
+
|
|
115
|
+
export function FilePreview({ fileName, base64 }: { fileName: string; base64: string }) {
|
|
116
|
+
return (
|
|
117
|
+
<PreviewComponent
|
|
118
|
+
fileName={fileName}
|
|
119
|
+
base64={base64}
|
|
120
|
+
className="h-96"
|
|
121
|
+
/>
|
|
122
|
+
);
|
|
123
|
+
}
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
Supported image extensions include `avif`, `bmp`, `gif`, `jpg`, `jpeg`, `png`, `svg`, and `webp`. Supported text extensions include `css`, `csv`, `html`, `js`, `jsx`, `md`, `ts`, `tsx`, `txt`, `xml`, `yaml`, and `yml`.
|
|
127
|
+
|
|
87
128
|
## Window components
|
|
88
129
|
|
|
89
130
|
### Simple window
|
|
@@ -207,6 +248,8 @@ The package exports these components and types for external use:
|
|
|
207
248
|
- `Input`
|
|
208
249
|
- `TextArea`
|
|
209
250
|
- `CodeEditor`
|
|
251
|
+
- `RichEditor`
|
|
252
|
+
- `PreviewComponent` (also available as `FilePreview`)
|
|
210
253
|
- `Select`
|
|
211
254
|
- `SelectOption`
|
|
212
255
|
- `Checkbox`
|
package/dist/index.cjs
CHANGED
|
@@ -354,7 +354,7 @@ var RichEditor = ({ content, onChange, isDarkTheme }) => {
|
|
|
354
354
|
}
|
|
355
355
|
}, [content, editor]);
|
|
356
356
|
return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
357
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mt-3 flex flex-wrap items-center gap-1 border-b border-primary pb-2
|
|
357
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mt-3 flex flex-wrap items-center gap-1 border-b border-primary pb-2", children: [
|
|
358
358
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-0.5", children: [
|
|
359
359
|
/* @__PURE__ */ jsxRuntime.jsx(Button_default, { type: "button", variant: editor?.isActive("bold") ? "primary" : "ghost", size: "sm", onClick: () => editor?.chain().focus().toggleBold().run(), "aria-label": "Bold text", title: "Bold", children: /* @__PURE__ */ jsxRuntime.jsx("strong", { children: "B" }) }),
|
|
360
360
|
/* @__PURE__ */ jsxRuntime.jsx(Button_default, { type: "button", variant: editor?.isActive("italic") ? "primary" : "ghost", size: "sm", onClick: () => editor?.chain().focus().toggleItalic().run(), "aria-label": "Italic text", title: "Italic", children: /* @__PURE__ */ jsxRuntime.jsx("em", { children: "I" }) }),
|
|
@@ -385,7 +385,7 @@ var RichEditor = ({ content, onChange, isDarkTheme }) => {
|
|
|
385
385
|
react$1.EditorContent,
|
|
386
386
|
{
|
|
387
387
|
editor,
|
|
388
|
-
className: `mt-4 min-h-52 rounded-md border border-
|
|
388
|
+
className: `mt-4 min-h-52 rounded-md border border-brand-color p-3 text-sm leading-6 text-neutral-500 outline-none transition-colors focus-within:border-brand-color [&_.ProseMirror]:min-h-44 [&_.ProseMirror]:outline-none [&_.ProseMirror_p]:my-2 [&_.ProseMirror_h1]:my-3 [&_.ProseMirror_h1]:text-2xl [&_.ProseMirror_h1]:font-bold [&_.ProseMirror_h2]:my-3 [&_.ProseMirror_h2]:text-xl [&_.ProseMirror_h2]:font-bold [&_.ProseMirror_h3]:my-3 [&_.ProseMirror_h3]:text-lg [&_.ProseMirror_h3]:font-bold [&_.ProseMirror_ul]:my-2 [&_.ProseMirror_ul]:list-disc [&_.ProseMirror_ul]:pl-6 [&_.ProseMirror_ol]:my-2 [&_.ProseMirror_ol]:list-decimal [&_.ProseMirror_ol]:pl-6 [&_.ProseMirror_blockquote]:my-3 [&_.ProseMirror_blockquote]:border-l-4 [&_.ProseMirror_blockquote]:border-brand-color [&_.ProseMirror_blockquote]:pl-4 [&_.ProseMirror_pre]:my-3 [&_.ProseMirror_pre]:overflow-x-auto [&_.ProseMirror_pre]:rounded [&_.ProseMirror_pre]:bg-surface-3 [&_.ProseMirror_pre]:p-3 ${editorTheme === "vs-dark" ? "bg-primary" : "bg-secondary"}`
|
|
389
389
|
}
|
|
390
390
|
)
|
|
391
391
|
] });
|
|
@@ -2318,6 +2318,67 @@ var Tabs = ({
|
|
|
2318
2318
|
] });
|
|
2319
2319
|
};
|
|
2320
2320
|
var Tabs_default = Tabs;
|
|
2321
|
+
var imageExtensions = /\.(avif|bmp|gif|jpe?g|png|svg|webp)$/i;
|
|
2322
|
+
var textExtensions = /\.(css|csv|html?|js|jsx|md|mjs|ts|tsx|txt|xml|yaml|yml)$/i;
|
|
2323
|
+
var getPreviewType = (fileName) => {
|
|
2324
|
+
if (/\.pdf$/i.test(fileName)) return "pdf";
|
|
2325
|
+
if (/\.json$/i.test(fileName)) return "json";
|
|
2326
|
+
if (imageExtensions.test(fileName)) return "image";
|
|
2327
|
+
if (textExtensions.test(fileName) || !fileName.includes(".")) return "text";
|
|
2328
|
+
return "unsupported";
|
|
2329
|
+
};
|
|
2330
|
+
var getMimeType = (fileName) => {
|
|
2331
|
+
const extension = fileName.split(".").pop()?.toLowerCase();
|
|
2332
|
+
const mimeTypes = {
|
|
2333
|
+
avif: "image/avif",
|
|
2334
|
+
bmp: "image/bmp",
|
|
2335
|
+
gif: "image/gif",
|
|
2336
|
+
jpeg: "image/jpeg",
|
|
2337
|
+
jpg: "image/jpeg",
|
|
2338
|
+
png: "image/png",
|
|
2339
|
+
svg: "image/svg+xml",
|
|
2340
|
+
webp: "image/webp",
|
|
2341
|
+
pdf: "application/pdf"
|
|
2342
|
+
};
|
|
2343
|
+
return mimeTypes[extension ?? ""] ?? "application/octet-stream";
|
|
2344
|
+
};
|
|
2345
|
+
var toDataUrl = (base64, fileName) => {
|
|
2346
|
+
if (base64.trim().startsWith("data:")) return base64;
|
|
2347
|
+
return `data:${getMimeType(fileName)};base64,${base64}`;
|
|
2348
|
+
};
|
|
2349
|
+
var decodeBase64 = (base64) => {
|
|
2350
|
+
const value = base64.includes(",") ? base64.slice(base64.indexOf(",") + 1) : base64;
|
|
2351
|
+
const bytes = Uint8Array.from(atob(value), (character) => character.charCodeAt(0));
|
|
2352
|
+
return new TextDecoder().decode(bytes);
|
|
2353
|
+
};
|
|
2354
|
+
var PreviewComponent = ({ fileName, base64, className }) => {
|
|
2355
|
+
const previewType = getPreviewType(fileName);
|
|
2356
|
+
const dataUrl = toDataUrl(base64, fileName);
|
|
2357
|
+
if (previewType === "image") {
|
|
2358
|
+
return /* @__PURE__ */ jsxRuntime.jsx("div", { className: cn("flex h-full min-h-48 w-full items-center justify-center overflow-auto", className), children: /* @__PURE__ */ jsxRuntime.jsx("img", { src: dataUrl, alt: fileName, className: "max-h-full max-w-full object-contain" }) });
|
|
2359
|
+
}
|
|
2360
|
+
if (previewType === "pdf") {
|
|
2361
|
+
return /* @__PURE__ */ jsxRuntime.jsx("iframe", { title: fileName, src: dataUrl, className: cn("h-full min-h-96 w-full border-0", className) });
|
|
2362
|
+
}
|
|
2363
|
+
if (previewType === "text" || previewType === "json") {
|
|
2364
|
+
let content;
|
|
2365
|
+
try {
|
|
2366
|
+
content = decodeBase64(base64);
|
|
2367
|
+
if (previewType === "json") {
|
|
2368
|
+
content = JSON.stringify(JSON.parse(content), null, 2);
|
|
2369
|
+
}
|
|
2370
|
+
} catch {
|
|
2371
|
+
content = "Unable to preview this file.";
|
|
2372
|
+
}
|
|
2373
|
+
return /* @__PURE__ */ jsxRuntime.jsx("pre", { className: cn("h-full min-h-48 w-full overflow-auto whitespace-pre-wrap break-words p-4 text-left", className), children: /* @__PURE__ */ jsxRuntime.jsx("code", { children: content }) });
|
|
2374
|
+
}
|
|
2375
|
+
return /* @__PURE__ */ jsxRuntime.jsx("div", { className: cn("flex min-h-48 items-center justify-center p-4 text-center", className), children: /* @__PURE__ */ jsxRuntime.jsxs("p", { children: [
|
|
2376
|
+
"Preview is not available for ",
|
|
2377
|
+
fileName,
|
|
2378
|
+
"."
|
|
2379
|
+
] }) });
|
|
2380
|
+
};
|
|
2381
|
+
var PreviewComponent_default = PreviewComponent;
|
|
2321
2382
|
var DEFAULT_BACKGROUND = "/wallpaper/Wallpaper3.webp";
|
|
2322
2383
|
var DEFAULT_MOCK_USER = {
|
|
2323
2384
|
id: "dev-user",
|
|
@@ -3520,6 +3581,7 @@ exports.Checkbox = Checkbox_default;
|
|
|
3520
3581
|
exports.CodeEditor = CodeEditor_default;
|
|
3521
3582
|
exports.Divider = Divider_default;
|
|
3522
3583
|
exports.Dropdown = Dropdown_default;
|
|
3584
|
+
exports.FilePreview = PreviewComponent_default;
|
|
3523
3585
|
exports.FileUpload = FileUpload_default;
|
|
3524
3586
|
exports.ImageWithPlaceholder = ImageWithPlaceholder_default;
|
|
3525
3587
|
exports.Input = Input_default;
|
|
@@ -3527,6 +3589,7 @@ exports.Loading = Loading_default;
|
|
|
3527
3589
|
exports.Modal = Modal_default;
|
|
3528
3590
|
exports.Pagination = Pagination_default;
|
|
3529
3591
|
exports.PluginPlayground = PluginPlayground;
|
|
3592
|
+
exports.PreviewComponent = PreviewComponent_default;
|
|
3530
3593
|
exports.Progress = Progress_default;
|
|
3531
3594
|
exports.Radio = Radio_default;
|
|
3532
3595
|
exports.RichEditor = RichEditor_default;
|