@cere/cere-design-system 0.0.29 → 0.0.30

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.mjs CHANGED
@@ -8723,7 +8723,8 @@ var CodeEditor = ({
8723
8723
  monacoRef,
8724
8724
  onFullscreenChange,
8725
8725
  containerProps,
8726
- typeDefinitions
8726
+ typeDefinitions,
8727
+ externalModelManagement = false
8727
8728
  }) => {
8728
8729
  const [isEditorReady, setIsEditorReady] = useState11(false);
8729
8730
  const [validationErrors, setValidationErrors] = useState11([]);
@@ -8869,6 +8870,7 @@ var CodeEditor = ({
8869
8870
  onChange(valueStr);
8870
8871
  };
8871
8872
  useEffect2(() => {
8873
+ if (externalModelManagement) return;
8872
8874
  if (value !== tsCode) {
8873
8875
  setTsCode(value);
8874
8876
  if (isEditorReady && finalEditorRef?.current) {
@@ -8879,7 +8881,7 @@ var CodeEditor = ({
8879
8881
  }
8880
8882
  }
8881
8883
  }
8882
- }, [value, tsCode, isEditorReady, finalEditorRef]);
8884
+ }, [value, tsCode, isEditorReady, finalEditorRef, externalModelManagement]);
8883
8885
  const editorMinHeight = minHeight ? typeof minHeight === "number" ? `${minHeight}px` : minHeight : "400px";
8884
8886
  const defaultOptions = {
8885
8887
  lineNumbers,
@@ -9107,6 +9109,832 @@ var WorkflowNodeHandle = ({
9107
9109
  /* @__PURE__ */ jsx97(Handle, { type: "source", position: Position.Right, style: handleStyle })
9108
9110
  ] });
9109
9111
  };
9112
+
9113
+ // src/components/third-party/CodeEditorWorkspace/CodeEditorWorkspace.types.ts
9114
+ var EXTENSION_LANGUAGE_MAP = {
9115
+ ts: "typescript",
9116
+ tsx: "typescript",
9117
+ js: "javascript",
9118
+ jsx: "javascript",
9119
+ json: "json",
9120
+ html: "html",
9121
+ htm: "html",
9122
+ css: "css",
9123
+ py: "python",
9124
+ yaml: "yaml",
9125
+ yml: "yaml",
9126
+ md: "markdown",
9127
+ sql: "sql",
9128
+ xml: "xml",
9129
+ txt: "plaintext"
9130
+ };
9131
+ function detectLanguage(path) {
9132
+ const ext = path.split(".").pop()?.toLowerCase() ?? "";
9133
+ return EXTENSION_LANGUAGE_MAP[ext] ?? "plaintext";
9134
+ }
9135
+ function getFileName(path) {
9136
+ return path.split("/").pop() ?? path;
9137
+ }
9138
+
9139
+ // src/components/third-party/CodeEditorWorkspace/useCodeEditorWorkspace.ts
9140
+ import { useCallback as useCallback9, useEffect as useEffect3, useRef as useRef3, useState as useState12 } from "react";
9141
+ function useCodeEditorWorkspace({
9142
+ files,
9143
+ initialOpenPaths,
9144
+ onFileChange,
9145
+ onValidationChange
9146
+ }) {
9147
+ const fileContentsRef = useRef3(/* @__PURE__ */ new Map());
9148
+ const originalContentsRef = useRef3(/* @__PURE__ */ new Map());
9149
+ const [openTabs, setOpenTabs] = useState12([]);
9150
+ const [activeFilePath, setActiveFilePath] = useState12(null);
9151
+ const monacoRef = useRef3(null);
9152
+ const editorRef = useRef3(null);
9153
+ const modelsRef = useRef3(/* @__PURE__ */ new Map());
9154
+ const [validationMarkers, setValidationMarkers] = useState12({});
9155
+ const [cursorPosition, setCursorPosition] = useState12(null);
9156
+ useEffect3(() => {
9157
+ for (const file of files) {
9158
+ if (!fileContentsRef.current.has(file.path)) {
9159
+ fileContentsRef.current.set(file.path, file.value);
9160
+ originalContentsRef.current.set(file.path, file.value);
9161
+ }
9162
+ const model = modelsRef.current.get(file.path);
9163
+ if (model && !model.isDisposed()) {
9164
+ if (file.value === fileContentsRef.current.get(file.path)) {
9165
+ originalContentsRef.current.set(file.path, file.value);
9166
+ continue;
9167
+ }
9168
+ if (originalContentsRef.current.get(file.path) !== file.value) {
9169
+ const localContent = fileContentsRef.current.get(file.path) ?? "";
9170
+ const previousOriginal = originalContentsRef.current.get(file.path) ?? "";
9171
+ originalContentsRef.current.set(file.path, file.value);
9172
+ if (localContent === previousOriginal) {
9173
+ fileContentsRef.current.set(file.path, file.value);
9174
+ model.setValue(file.value);
9175
+ }
9176
+ }
9177
+ }
9178
+ }
9179
+ }, [files]);
9180
+ useEffect3(() => {
9181
+ if (initialOpenPaths && initialOpenPaths.length > 0) {
9182
+ const tabs = initialOpenPaths.filter((p) => files.some((f) => f.path === p)).map((p) => ({
9183
+ path: p,
9184
+ label: getFileName(p),
9185
+ isDirty: false
9186
+ }));
9187
+ if (tabs.length > 0) {
9188
+ setOpenTabs(tabs);
9189
+ setActiveFilePath(tabs[0].path);
9190
+ }
9191
+ }
9192
+ }, []);
9193
+ const getOrCreateModel = useCallback9(
9194
+ (path) => {
9195
+ const monaco = monacoRef.current;
9196
+ if (!monaco) return null;
9197
+ const existing = modelsRef.current.get(path);
9198
+ if (existing && !existing.isDisposed()) return existing;
9199
+ const file = files.find((f) => f.path === path);
9200
+ const content = fileContentsRef.current.get(path) ?? file?.value ?? "";
9201
+ const lang = file?.language ?? detectLanguage(path);
9202
+ const uri = monaco.Uri.parse(`file:///${path}`);
9203
+ let model = monaco.editor.getModel(uri);
9204
+ if (!model) {
9205
+ model = monaco.editor.createModel(content, lang, uri);
9206
+ }
9207
+ modelsRef.current.set(path, model);
9208
+ return model;
9209
+ },
9210
+ [files]
9211
+ );
9212
+ const disposeModel = useCallback9((path) => {
9213
+ const model = modelsRef.current.get(path);
9214
+ if (model && !model.isDisposed()) {
9215
+ model.dispose();
9216
+ }
9217
+ modelsRef.current.delete(path);
9218
+ }, []);
9219
+ const switchToFile = useCallback9(
9220
+ (path) => {
9221
+ const ed = editorRef.current;
9222
+ if (!ed) return;
9223
+ const model = getOrCreateModel(path);
9224
+ if (model) {
9225
+ ed.setModel(model);
9226
+ }
9227
+ },
9228
+ [getOrCreateModel]
9229
+ );
9230
+ const openFile = useCallback9(
9231
+ (path) => {
9232
+ const file = files.find((f) => f.path === path);
9233
+ if (!file) return;
9234
+ if (!fileContentsRef.current.has(path)) {
9235
+ fileContentsRef.current.set(path, file.value);
9236
+ originalContentsRef.current.set(path, file.value);
9237
+ }
9238
+ setOpenTabs((prev) => {
9239
+ const exists = prev.some((t) => t.path === path);
9240
+ if (exists) return prev;
9241
+ return [
9242
+ ...prev,
9243
+ { path, label: getFileName(path), isDirty: false }
9244
+ ];
9245
+ });
9246
+ setActiveFilePath(path);
9247
+ switchToFile(path);
9248
+ },
9249
+ [files, switchToFile]
9250
+ );
9251
+ const closeFile = useCallback9(
9252
+ (path) => {
9253
+ disposeModel(path);
9254
+ setOpenTabs((prev) => {
9255
+ const newTabs = prev.filter((t) => t.path !== path);
9256
+ if (activeFilePath === path) {
9257
+ const closedIndex = prev.findIndex((t) => t.path === path);
9258
+ const nextTab = newTabs[Math.min(closedIndex, newTabs.length - 1)] ?? null;
9259
+ const nextPath = nextTab?.path ?? null;
9260
+ setActiveFilePath(nextPath);
9261
+ if (nextPath) {
9262
+ switchToFile(nextPath);
9263
+ }
9264
+ }
9265
+ return newTabs;
9266
+ });
9267
+ },
9268
+ [activeFilePath, disposeModel, switchToFile]
9269
+ );
9270
+ const setActiveFileAction = useCallback9(
9271
+ (path) => {
9272
+ setActiveFilePath(path);
9273
+ switchToFile(path);
9274
+ },
9275
+ [switchToFile]
9276
+ );
9277
+ const updateFileContent = useCallback9(
9278
+ (path, value) => {
9279
+ fileContentsRef.current.set(path, value);
9280
+ const model = modelsRef.current.get(path);
9281
+ if (model && !model.isDisposed() && model.getValue() !== value) {
9282
+ model.setValue(value);
9283
+ }
9284
+ const isDirty = value !== originalContentsRef.current.get(path);
9285
+ setOpenTabs(
9286
+ (prev) => prev.map((t) => t.path === path ? { ...t, isDirty } : t)
9287
+ );
9288
+ onFileChange?.(path, value);
9289
+ },
9290
+ [onFileChange]
9291
+ );
9292
+ const getFileContent = useCallback9((path) => {
9293
+ return fileContentsRef.current.get(path);
9294
+ }, []);
9295
+ const markSaved = useCallback9((path) => {
9296
+ const content = fileContentsRef.current.get(path);
9297
+ if (content !== void 0) {
9298
+ originalContentsRef.current.set(path, content);
9299
+ }
9300
+ setOpenTabs(
9301
+ (prev) => prev.map((t) => t.path === path ? { ...t, isDirty: false } : t)
9302
+ );
9303
+ }, []);
9304
+ const markAllSaved = useCallback9(() => {
9305
+ for (const [path, content] of fileContentsRef.current.entries()) {
9306
+ originalContentsRef.current.set(path, content);
9307
+ }
9308
+ setOpenTabs((prev) => prev.map((t) => ({ ...t, isDirty: false })));
9309
+ }, []);
9310
+ const handleEditorMount = useCallback9(
9311
+ (editorInstance, monacoInstance) => {
9312
+ monacoRef.current = monacoInstance;
9313
+ editorRef.current = editorInstance;
9314
+ if (activeFilePath) {
9315
+ const model = getOrCreateModel(activeFilePath);
9316
+ if (model) {
9317
+ editorInstance.setModel(model);
9318
+ }
9319
+ }
9320
+ editorInstance.onDidChangeCursorPosition((e) => {
9321
+ setCursorPosition({ line: e.position.lineNumber, column: e.position.column });
9322
+ });
9323
+ const pos = editorInstance.getPosition();
9324
+ if (pos) {
9325
+ setCursorPosition({ line: pos.lineNumber, column: pos.column });
9326
+ }
9327
+ monacoInstance.editor.onDidChangeMarkers((uris) => {
9328
+ const newMarkers = { ...validationMarkers };
9329
+ for (const uri of uris) {
9330
+ const path = uri.path.replace(/^\//, "");
9331
+ const markers = monacoInstance.editor.getModelMarkers({ resource: uri });
9332
+ newMarkers[path] = markers;
9333
+ }
9334
+ setValidationMarkers(newMarkers);
9335
+ onValidationChange?.(newMarkers);
9336
+ });
9337
+ },
9338
+ // eslint-disable-next-line react-hooks/exhaustive-deps
9339
+ [activeFilePath, getOrCreateModel, onValidationChange]
9340
+ );
9341
+ const handleEditorChange = useCallback9(
9342
+ (value) => {
9343
+ if (!activeFilePath) return;
9344
+ fileContentsRef.current.set(activeFilePath, value);
9345
+ const isDirty = value !== originalContentsRef.current.get(activeFilePath);
9346
+ setOpenTabs(
9347
+ (prev) => prev.map(
9348
+ (t) => t.path === activeFilePath ? { ...t, isDirty } : t
9349
+ )
9350
+ );
9351
+ onFileChange?.(activeFilePath, value);
9352
+ },
9353
+ [activeFilePath, onFileChange]
9354
+ );
9355
+ const activeFile = activeFilePath ? {
9356
+ path: activeFilePath,
9357
+ value: fileContentsRef.current.get(activeFilePath) ?? "",
9358
+ language: files.find((f) => f.path === activeFilePath)?.language ?? detectLanguage(activeFilePath)
9359
+ } : void 0;
9360
+ useEffect3(() => {
9361
+ return () => {
9362
+ for (const model of modelsRef.current.values()) {
9363
+ if (!model.isDisposed()) {
9364
+ model.dispose();
9365
+ }
9366
+ }
9367
+ modelsRef.current.clear();
9368
+ };
9369
+ }, []);
9370
+ return {
9371
+ openTabs,
9372
+ activeFilePath,
9373
+ openFile,
9374
+ closeFile,
9375
+ setActiveFile: setActiveFileAction,
9376
+ updateFileContent,
9377
+ getFileContent,
9378
+ activeFile,
9379
+ monacoRef,
9380
+ editorRef,
9381
+ handleEditorMount,
9382
+ handleEditorChange,
9383
+ validationMarkers,
9384
+ markSaved,
9385
+ markAllSaved,
9386
+ cursorPosition
9387
+ };
9388
+ }
9389
+
9390
+ // src/components/third-party/CodeEditorWorkspace/CodeEditorTabs.tsx
9391
+ import React14 from "react";
9392
+ import { Box as Box31, IconButton as IconButton15, Tooltip as Tooltip8, Typography as Typography27 } from "@mui/material";
9393
+ import CloseIcon5 from "@mui/icons-material/Close";
9394
+ import { jsx as jsx98, jsxs as jsxs50 } from "react/jsx-runtime";
9395
+ var CodeEditorTabs = ({
9396
+ tabs,
9397
+ activeTab,
9398
+ onTabSelect,
9399
+ onTabClose,
9400
+ renderTab,
9401
+ containerProps
9402
+ }) => {
9403
+ if (tabs.length === 0) return null;
9404
+ return /* @__PURE__ */ jsx98(
9405
+ Box31,
9406
+ {
9407
+ sx: {
9408
+ display: "flex",
9409
+ alignItems: "stretch",
9410
+ overflow: "auto",
9411
+ minHeight: 36,
9412
+ borderBottom: 1,
9413
+ borderColor: "divider",
9414
+ bgcolor: "background.default",
9415
+ "&::-webkit-scrollbar": { height: 2 },
9416
+ "&::-webkit-scrollbar-thumb": { bgcolor: "action.disabled", borderRadius: 1 }
9417
+ },
9418
+ ...containerProps,
9419
+ children: tabs.map((tab) => {
9420
+ const isActive = tab.path === activeTab;
9421
+ const label = tab.label ?? getFileName(tab.path);
9422
+ if (renderTab) {
9423
+ return /* @__PURE__ */ jsx98(React14.Fragment, { children: renderTab({
9424
+ tab,
9425
+ isActive,
9426
+ onSelect: () => onTabSelect?.(tab.path),
9427
+ onClose: () => onTabClose?.(tab.path)
9428
+ }) }, tab.path);
9429
+ }
9430
+ return /* @__PURE__ */ jsxs50(
9431
+ Box31,
9432
+ {
9433
+ onClick: () => onTabSelect?.(tab.path),
9434
+ sx: {
9435
+ display: "flex",
9436
+ alignItems: "center",
9437
+ gap: 0.5,
9438
+ px: 1.5,
9439
+ py: 0.5,
9440
+ cursor: "pointer",
9441
+ whiteSpace: "nowrap",
9442
+ borderRight: 1,
9443
+ borderColor: "divider",
9444
+ bgcolor: isActive ? "background.paper" : "transparent",
9445
+ borderBottom: isActive ? "2px solid" : "2px solid transparent",
9446
+ borderBottomColor: isActive ? "primary.main" : "transparent",
9447
+ "&:hover": {
9448
+ bgcolor: isActive ? "background.paper" : "action.hover"
9449
+ },
9450
+ transition: "background-color 0.15s ease"
9451
+ },
9452
+ children: [
9453
+ tab.isDirty && /* @__PURE__ */ jsx98(
9454
+ Box31,
9455
+ {
9456
+ sx: {
9457
+ width: 6,
9458
+ height: 6,
9459
+ borderRadius: "50%",
9460
+ bgcolor: "warning.main",
9461
+ flexShrink: 0
9462
+ }
9463
+ }
9464
+ ),
9465
+ /* @__PURE__ */ jsx98(Tooltip8, { title: tab.path, enterDelay: 600, children: /* @__PURE__ */ jsx98(
9466
+ Typography27,
9467
+ {
9468
+ variant: "body2",
9469
+ sx: {
9470
+ fontSize: "0.8125rem",
9471
+ fontWeight: isActive ? 600 : 400,
9472
+ color: isActive ? "text.primary" : "text.secondary",
9473
+ userSelect: "none"
9474
+ },
9475
+ children: label
9476
+ }
9477
+ ) }),
9478
+ onTabClose && /* @__PURE__ */ jsx98(
9479
+ IconButton15,
9480
+ {
9481
+ size: "small",
9482
+ onClick: (e) => {
9483
+ e.stopPropagation();
9484
+ onTabClose(tab.path);
9485
+ },
9486
+ sx: {
9487
+ p: 0.25,
9488
+ ml: 0.5,
9489
+ opacity: isActive ? 0.7 : 0,
9490
+ "&:hover": { opacity: 1 },
9491
+ ".MuiBox-root:hover > &": { opacity: 0.5 },
9492
+ transition: "opacity 0.15s ease"
9493
+ },
9494
+ "aria-label": `Close ${label}`,
9495
+ children: /* @__PURE__ */ jsx98(CloseIcon5, { sx: { fontSize: 14 } })
9496
+ }
9497
+ )
9498
+ ]
9499
+ },
9500
+ tab.path
9501
+ );
9502
+ })
9503
+ }
9504
+ );
9505
+ };
9506
+
9507
+ // src/components/third-party/CodeEditorWorkspace/CodeEditorFileTree.tsx
9508
+ import React15, { useCallback as useCallback10, useState as useState13 } from "react";
9509
+ import { Box as Box32, Collapse as Collapse2, List as List7, ListItemButton as ListItemButton4, ListItemIcon as ListItemIcon6, ListItemText as ListItemText9 } from "@mui/material";
9510
+ import FolderIcon2 from "@mui/icons-material/Folder";
9511
+ import FolderOpenIcon from "@mui/icons-material/FolderOpen";
9512
+ import InsertDriveFileOutlinedIcon from "@mui/icons-material/InsertDriveFileOutlined";
9513
+ import ExpandMoreIcon4 from "@mui/icons-material/ExpandMore";
9514
+ import ChevronRightIcon4 from "@mui/icons-material/ChevronRight";
9515
+ import { jsx as jsx99, jsxs as jsxs51 } from "react/jsx-runtime";
9516
+ var CodeEditorFileTree = ({
9517
+ tree,
9518
+ selectedPath,
9519
+ onFileSelect,
9520
+ onFolderToggle,
9521
+ renderNode,
9522
+ defaultExpandedPaths,
9523
+ width = 220,
9524
+ containerProps
9525
+ }) => {
9526
+ const [expandedPaths, setExpandedPaths] = useState13(
9527
+ () => new Set(defaultExpandedPaths ?? [])
9528
+ );
9529
+ const toggleFolder = useCallback10(
9530
+ (path) => {
9531
+ setExpandedPaths((prev) => {
9532
+ const next = new Set(prev);
9533
+ const isExpanded = next.has(path);
9534
+ if (isExpanded) {
9535
+ next.delete(path);
9536
+ } else {
9537
+ next.add(path);
9538
+ }
9539
+ onFolderToggle?.(path, !isExpanded);
9540
+ return next;
9541
+ });
9542
+ },
9543
+ [onFolderToggle]
9544
+ );
9545
+ const renderTreeNode = (node, depth) => {
9546
+ const isFolder = node.type === "folder";
9547
+ const isExpanded = expandedPaths.has(node.path);
9548
+ const isSelected = node.path === selectedPath;
9549
+ if (renderNode) {
9550
+ return /* @__PURE__ */ jsxs51(React15.Fragment, { children: [
9551
+ renderNode({
9552
+ node,
9553
+ depth,
9554
+ isSelected,
9555
+ isExpanded,
9556
+ onSelect: () => {
9557
+ if (isFolder) {
9558
+ toggleFolder(node.path);
9559
+ } else {
9560
+ onFileSelect?.(node.path);
9561
+ }
9562
+ },
9563
+ onToggle: () => toggleFolder(node.path)
9564
+ }),
9565
+ isFolder && isExpanded && node.children?.map((child) => renderTreeNode(child, depth + 1))
9566
+ ] }, node.path);
9567
+ }
9568
+ return /* @__PURE__ */ jsxs51(React15.Fragment, { children: [
9569
+ /* @__PURE__ */ jsxs51(
9570
+ ListItemButton4,
9571
+ {
9572
+ selected: isSelected,
9573
+ onClick: () => {
9574
+ if (isFolder) {
9575
+ toggleFolder(node.path);
9576
+ } else {
9577
+ onFileSelect?.(node.path);
9578
+ }
9579
+ },
9580
+ sx: {
9581
+ pl: 1 + depth * 1.5,
9582
+ py: 0.25,
9583
+ minHeight: 28,
9584
+ "&.Mui-selected": {
9585
+ bgcolor: "action.selected",
9586
+ "&:hover": { bgcolor: "action.selected" }
9587
+ }
9588
+ },
9589
+ children: [
9590
+ isFolder && /* @__PURE__ */ jsx99(ListItemIcon6, { sx: { minWidth: 20 }, children: isExpanded ? /* @__PURE__ */ jsx99(ExpandMoreIcon4, { sx: { fontSize: 16 } }) : /* @__PURE__ */ jsx99(ChevronRightIcon4, { sx: { fontSize: 16 } }) }),
9591
+ /* @__PURE__ */ jsx99(ListItemIcon6, { sx: { minWidth: 24 }, children: node.icon ?? (isFolder ? isExpanded ? /* @__PURE__ */ jsx99(FolderOpenIcon, { sx: { fontSize: 16, color: "warning.main" } }) : /* @__PURE__ */ jsx99(FolderIcon2, { sx: { fontSize: 16, color: "warning.main" } }) : /* @__PURE__ */ jsx99(InsertDriveFileOutlinedIcon, { sx: { fontSize: 16, color: "text.secondary" } })) }),
9592
+ /* @__PURE__ */ jsx99(
9593
+ ListItemText9,
9594
+ {
9595
+ primary: node.name,
9596
+ slotProps: {
9597
+ primary: {
9598
+ sx: {
9599
+ fontSize: "0.8125rem",
9600
+ fontWeight: isSelected ? 600 : 400,
9601
+ overflow: "hidden",
9602
+ textOverflow: "ellipsis",
9603
+ whiteSpace: "nowrap"
9604
+ }
9605
+ }
9606
+ }
9607
+ }
9608
+ )
9609
+ ]
9610
+ }
9611
+ ),
9612
+ isFolder && /* @__PURE__ */ jsx99(Collapse2, { in: isExpanded, timeout: "auto", unmountOnExit: true, children: node.children?.map((child) => renderTreeNode(child, depth + 1)) })
9613
+ ] }, node.path);
9614
+ };
9615
+ return /* @__PURE__ */ jsx99(
9616
+ Box32,
9617
+ {
9618
+ sx: {
9619
+ width: typeof width === "number" ? `${width}px` : width,
9620
+ minWidth: typeof width === "number" ? `${width}px` : width,
9621
+ height: "100%",
9622
+ overflow: "auto",
9623
+ borderRight: 1,
9624
+ borderColor: "divider",
9625
+ bgcolor: "background.default"
9626
+ },
9627
+ ...containerProps,
9628
+ children: /* @__PURE__ */ jsx99(List7, { dense: true, disablePadding: true, children: tree.map((node) => renderTreeNode(node, 0)) })
9629
+ }
9630
+ );
9631
+ };
9632
+
9633
+ // src/components/third-party/CodeEditorWorkspace/CodeEditorStatusBar.tsx
9634
+ import { Box as Box33, Tooltip as Tooltip9, Typography as Typography28 } from "@mui/material";
9635
+ import { Fragment as Fragment16, jsx as jsx100, jsxs as jsxs52 } from "react/jsx-runtime";
9636
+ var LANGUAGE_LABELS = {
9637
+ typescript: "TypeScript",
9638
+ javascript: "JavaScript",
9639
+ json: "JSON",
9640
+ html: "HTML",
9641
+ css: "CSS",
9642
+ python: "Python",
9643
+ yaml: "YAML",
9644
+ markdown: "Markdown",
9645
+ sql: "SQL",
9646
+ xml: "XML",
9647
+ plaintext: "Plain Text"
9648
+ };
9649
+ var CodeEditorStatusBar = ({
9650
+ gitInfo,
9651
+ language,
9652
+ cursorPosition,
9653
+ items,
9654
+ renderStatusBar,
9655
+ containerProps
9656
+ }) => {
9657
+ if (renderStatusBar) {
9658
+ return /* @__PURE__ */ jsx100(Fragment16, { children: renderStatusBar({ gitInfo, language, cursorPosition, items }) });
9659
+ }
9660
+ const leftItems = items?.filter((i) => i.align !== "right") ?? [];
9661
+ const rightItems = items?.filter((i) => i.align === "right") ?? [];
9662
+ return /* @__PURE__ */ jsxs52(
9663
+ Box33,
9664
+ {
9665
+ sx: {
9666
+ display: "flex",
9667
+ alignItems: "center",
9668
+ justifyContent: "space-between",
9669
+ px: 1.5,
9670
+ py: 0.25,
9671
+ minHeight: 24,
9672
+ borderTop: 1,
9673
+ borderColor: "divider",
9674
+ bgcolor: "primary.main",
9675
+ color: "primary.contrastText",
9676
+ fontSize: "0.75rem",
9677
+ fontFamily: 'Monaco, Menlo, "Ubuntu Mono", Consolas, monospace',
9678
+ gap: 1,
9679
+ flexShrink: 0
9680
+ },
9681
+ ...containerProps,
9682
+ children: [
9683
+ /* @__PURE__ */ jsxs52(Box33, { sx: { display: "flex", alignItems: "center", gap: 1.5, overflow: "hidden" }, children: [
9684
+ gitInfo && /* @__PURE__ */ jsx100(
9685
+ Tooltip9,
9686
+ {
9687
+ title: [
9688
+ gitInfo.remote && `Remote: ${gitInfo.remote}`,
9689
+ gitInfo.commitHash && `Commit: ${gitInfo.commitHash}`,
9690
+ gitInfo.ahead != null && `\u2191 ${gitInfo.ahead} ahead`,
9691
+ gitInfo.behind != null && `\u2193 ${gitInfo.behind} behind`
9692
+ ].filter(Boolean).join(" \xB7 ") || gitInfo.branch,
9693
+ enterDelay: 400,
9694
+ children: /* @__PURE__ */ jsxs52(
9695
+ Box33,
9696
+ {
9697
+ sx: {
9698
+ display: "flex",
9699
+ alignItems: "center",
9700
+ gap: 0.5,
9701
+ cursor: "default",
9702
+ overflow: "hidden"
9703
+ },
9704
+ children: [
9705
+ /* @__PURE__ */ jsx100(
9706
+ "svg",
9707
+ {
9708
+ width: "14",
9709
+ height: "14",
9710
+ viewBox: "0 0 16 16",
9711
+ fill: "currentColor",
9712
+ style: { flexShrink: 0 },
9713
+ children: /* @__PURE__ */ jsx100(
9714
+ "path",
9715
+ {
9716
+ fillRule: "evenodd",
9717
+ d: "M11.75 2.5a.75.75 0 1 0 0 1.5.75.75 0 0 0 0-1.5zm-2.25.75a2.25 2.25 0 1 1 3 2.122V6A2.5 2.5 0 0 1 10 8.5H6a1 1 0 0 0-1 1v1.128a2.251 2.251 0 1 1-1.5 0V5.372a2.25 2.25 0 1 1 1.5 0v1.836A2.492 2.492 0 0 1 6 7h4a1 1 0 0 0 1-1v-.628A2.25 2.25 0 0 1 9.5 3.25zM4.25 12a.75.75 0 1 0 0 1.5.75.75 0 0 0 0-1.5zM3.5 3.25a.75.75 0 1 1 1.5 0 .75.75 0 0 1-1.5 0z"
9718
+ }
9719
+ )
9720
+ }
9721
+ ),
9722
+ /* @__PURE__ */ jsx100(
9723
+ Typography28,
9724
+ {
9725
+ variant: "caption",
9726
+ sx: {
9727
+ fontSize: "inherit",
9728
+ fontFamily: "inherit",
9729
+ color: "inherit",
9730
+ lineHeight: 1,
9731
+ overflow: "hidden",
9732
+ textOverflow: "ellipsis",
9733
+ whiteSpace: "nowrap",
9734
+ maxWidth: 180
9735
+ },
9736
+ children: gitInfo.branch
9737
+ }
9738
+ ),
9739
+ gitInfo.isDirty && /* @__PURE__ */ jsx100(
9740
+ Box33,
9741
+ {
9742
+ component: "span",
9743
+ sx: {
9744
+ width: 6,
9745
+ height: 6,
9746
+ borderRadius: "50%",
9747
+ bgcolor: "warning.light",
9748
+ flexShrink: 0
9749
+ }
9750
+ }
9751
+ ),
9752
+ gitInfo.ahead != null && gitInfo.ahead > 0 && /* @__PURE__ */ jsxs52(Typography28, { variant: "caption", sx: { fontSize: "inherit", fontFamily: "inherit", color: "inherit", lineHeight: 1, opacity: 0.85 }, children: [
9753
+ "\u2191",
9754
+ gitInfo.ahead
9755
+ ] }),
9756
+ gitInfo.behind != null && gitInfo.behind > 0 && /* @__PURE__ */ jsxs52(Typography28, { variant: "caption", sx: { fontSize: "inherit", fontFamily: "inherit", color: "inherit", lineHeight: 1, opacity: 0.85 }, children: [
9757
+ "\u2193",
9758
+ gitInfo.behind
9759
+ ] })
9760
+ ]
9761
+ }
9762
+ )
9763
+ }
9764
+ ),
9765
+ leftItems.map((item) => /* @__PURE__ */ jsx100(StatusBarItemElement, { item }, item.id))
9766
+ ] }),
9767
+ /* @__PURE__ */ jsxs52(Box33, { sx: { display: "flex", alignItems: "center", gap: 1.5, overflow: "hidden" }, children: [
9768
+ rightItems.map((item) => /* @__PURE__ */ jsx100(StatusBarItemElement, { item }, item.id)),
9769
+ cursorPosition && /* @__PURE__ */ jsxs52(
9770
+ Typography28,
9771
+ {
9772
+ variant: "caption",
9773
+ sx: { fontSize: "inherit", fontFamily: "inherit", color: "inherit", lineHeight: 1, whiteSpace: "nowrap" },
9774
+ children: [
9775
+ "Ln ",
9776
+ cursorPosition.line,
9777
+ ", Col ",
9778
+ cursorPosition.column
9779
+ ]
9780
+ }
9781
+ ),
9782
+ language && /* @__PURE__ */ jsx100(
9783
+ Typography28,
9784
+ {
9785
+ variant: "caption",
9786
+ sx: { fontSize: "inherit", fontFamily: "inherit", color: "inherit", lineHeight: 1, whiteSpace: "nowrap" },
9787
+ children: LANGUAGE_LABELS[language] ?? language
9788
+ }
9789
+ )
9790
+ ] })
9791
+ ]
9792
+ }
9793
+ );
9794
+ };
9795
+ var StatusBarItemElement = ({ item }) => {
9796
+ const inner = /* @__PURE__ */ jsx100(
9797
+ Box33,
9798
+ {
9799
+ onClick: item.onClick,
9800
+ sx: {
9801
+ display: "flex",
9802
+ alignItems: "center",
9803
+ cursor: item.onClick ? "pointer" : "default",
9804
+ lineHeight: 1,
9805
+ whiteSpace: "nowrap",
9806
+ "&:hover": item.onClick ? { opacity: 0.8 } : void 0
9807
+ },
9808
+ children: typeof item.content === "string" ? /* @__PURE__ */ jsx100(
9809
+ Typography28,
9810
+ {
9811
+ variant: "caption",
9812
+ sx: { fontSize: "inherit", fontFamily: "inherit", color: "inherit", lineHeight: 1 },
9813
+ children: item.content
9814
+ }
9815
+ ) : item.content
9816
+ }
9817
+ );
9818
+ if (item.tooltip) {
9819
+ return /* @__PURE__ */ jsx100(Tooltip9, { title: item.tooltip, enterDelay: 400, children: inner });
9820
+ }
9821
+ return inner;
9822
+ };
9823
+
9824
+ // src/components/third-party/CodeEditorWorkspace/CodeEditorWorkspace.tsx
9825
+ import React16 from "react";
9826
+ import { Box as Box34 } from "@mui/material";
9827
+ import { jsx as jsx101, jsxs as jsxs53 } from "react/jsx-runtime";
9828
+ var CodeEditorWorkspace = ({
9829
+ files,
9830
+ initialOpenPaths,
9831
+ onFileChange,
9832
+ onValidationChange,
9833
+ fileTree,
9834
+ defaultExpandedPaths,
9835
+ showTabs = true,
9836
+ showFileTree = true,
9837
+ fileTreeWidth = 220,
9838
+ height = "500px",
9839
+ editorProps,
9840
+ containerProps,
9841
+ renderTabs,
9842
+ renderFileTree,
9843
+ renderEditor,
9844
+ renderStatusBar,
9845
+ gitInfo,
9846
+ showStatusBar = true,
9847
+ statusBarItems,
9848
+ onWorkspaceReady
9849
+ }) => {
9850
+ const workspace = useCodeEditorWorkspace({
9851
+ files,
9852
+ initialOpenPaths,
9853
+ onFileChange,
9854
+ onValidationChange
9855
+ });
9856
+ React16.useEffect(() => {
9857
+ onWorkspaceReady?.(workspace);
9858
+ }, []);
9859
+ const hasFileTree = showFileTree && fileTree && fileTree.length > 0;
9860
+ const tabsProps = {
9861
+ tabs: workspace.openTabs,
9862
+ activeTab: workspace.activeFilePath,
9863
+ onTabSelect: workspace.setActiveFile,
9864
+ onTabClose: workspace.closeFile
9865
+ };
9866
+ const tabsElement = showTabs ? renderTabs ? renderTabs({ ...tabsProps, workspace }) : /* @__PURE__ */ jsx101(CodeEditorTabs, { ...tabsProps }) : null;
9867
+ const fileTreeProps = {
9868
+ tree: fileTree ?? [],
9869
+ selectedPath: workspace.activeFilePath,
9870
+ onFileSelect: workspace.openFile,
9871
+ defaultExpandedPaths,
9872
+ width: fileTreeWidth
9873
+ };
9874
+ const fileTreeElement = hasFileTree ? renderFileTree ? renderFileTree({ ...fileTreeProps, workspace }) : /* @__PURE__ */ jsx101(CodeEditorFileTree, { ...fileTreeProps }) : null;
9875
+ const statusBarProps = {
9876
+ gitInfo,
9877
+ language: workspace.activeFile?.language,
9878
+ cursorPosition: workspace.cursorPosition ?? void 0,
9879
+ items: statusBarItems
9880
+ };
9881
+ const statusBarElement = showStatusBar ? renderStatusBar ? renderStatusBar({ ...statusBarProps, workspace }) : /* @__PURE__ */ jsx101(CodeEditorStatusBar, { ...statusBarProps }) : null;
9882
+ const editorElement = renderEditor ? renderEditor(workspace) : workspace.activeFile ? /* @__PURE__ */ jsx101(
9883
+ CodeEditor,
9884
+ {
9885
+ value: workspace.activeFile.value,
9886
+ onChange: workspace.handleEditorChange,
9887
+ language: workspace.activeFile.language,
9888
+ editorRef: workspace.editorRef,
9889
+ monacoRef: workspace.monacoRef,
9890
+ onMount: workspace.handleEditorMount,
9891
+ onValidate: (markers) => {
9892
+ if (workspace.activeFilePath) {
9893
+ workspace.validationMarkers[workspace.activeFilePath] = markers;
9894
+ }
9895
+ },
9896
+ externalModelManagement: true,
9897
+ height: "100%",
9898
+ ...editorProps
9899
+ }
9900
+ ) : /* @__PURE__ */ jsx101(
9901
+ Box34,
9902
+ {
9903
+ sx: {
9904
+ flex: 1,
9905
+ display: "flex",
9906
+ alignItems: "center",
9907
+ justifyContent: "center",
9908
+ color: "text.secondary",
9909
+ fontSize: "0.875rem"
9910
+ },
9911
+ children: "Open a file to start editing"
9912
+ }
9913
+ );
9914
+ return /* @__PURE__ */ jsxs53(
9915
+ Box34,
9916
+ {
9917
+ sx: {
9918
+ display: "flex",
9919
+ height: typeof height === "number" ? `${height}px` : height,
9920
+ border: 1,
9921
+ borderColor: "divider",
9922
+ borderRadius: 1,
9923
+ overflow: "hidden",
9924
+ bgcolor: "background.paper"
9925
+ },
9926
+ ...containerProps,
9927
+ children: [
9928
+ fileTreeElement,
9929
+ /* @__PURE__ */ jsxs53(Box34, { sx: { flex: 1, display: "flex", flexDirection: "column", minWidth: 0, overflow: "hidden" }, children: [
9930
+ tabsElement,
9931
+ /* @__PURE__ */ jsx101(Box34, { sx: { flex: 1, overflow: "hidden" }, children: editorElement }),
9932
+ statusBarElement
9933
+ ] })
9934
+ ]
9935
+ }
9936
+ );
9937
+ };
9110
9938
  export {
9111
9939
  Accordion,
9112
9940
  AccountSection,
@@ -9138,6 +9966,10 @@ export {
9138
9966
  ClockIcon,
9139
9967
  CloudFlashIcon,
9140
9968
  CodeEditor,
9969
+ CodeEditorFileTree,
9970
+ CodeEditorStatusBar,
9971
+ CodeEditorTabs,
9972
+ CodeEditorWorkspace,
9141
9973
  Collapse,
9142
9974
  ConnectionLineType2 as ConnectionLineType,
9143
9975
  ConnectionStatus,
@@ -9156,6 +9988,7 @@ export {
9156
9988
  Drawer2 as Drawer,
9157
9989
  Dropdown,
9158
9990
  DropdownAnchor,
9991
+ EXTENSION_LANGUAGE_MAP,
9159
9992
  EmptyState,
9160
9993
  EntityHeader,
9161
9994
  FilledFolderIcon,
@@ -9242,9 +10075,12 @@ export {
9242
10075
  WorkspaceSelectorButton,
9243
10076
  colors,
9244
10077
  contextMenuItems,
10078
+ detectLanguage,
10079
+ getFileName,
9245
10080
  robPaletteExtended,
9246
10081
  robPrimaryPalette,
9247
10082
  theme,
10083
+ useCodeEditorWorkspace,
9248
10084
  useIsDesktop,
9249
10085
  useIsMobile,
9250
10086
  useIsTablet,