rita-workspace 0.2.1 → 0.3.1

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.d.mts CHANGED
@@ -52,12 +52,48 @@ declare function addDrawingToWorkspace(workspaceId: string, drawingId: string):
52
52
  declare function removeDrawingFromWorkspace(workspaceId: string, drawingId: string): Promise<Workspace | undefined>;
53
53
  declare function setActiveDrawing(workspaceId: string, drawingId: string): Promise<Workspace | undefined>;
54
54
 
55
+ /**
56
+ * Rita Workspace Translations
57
+ *
58
+ * Supports Swedish (sv) and English (en)
59
+ */
60
+ type SupportedLanguage = 'sv' | 'en';
61
+ interface Translations {
62
+ drawings: string;
63
+ newDrawing: string;
64
+ manageDrawings: string;
65
+ dialogTitle: string;
66
+ close: string;
67
+ open: string;
68
+ rename: string;
69
+ delete: string;
70
+ save: string;
71
+ cancel: string;
72
+ confirm: string;
73
+ noDrawingsYet: string;
74
+ clickNewToStart: string;
75
+ modified: string;
76
+ confirmDelete: string;
77
+ shortcutNewDrawing: string;
78
+ }
79
+ /**
80
+ * Get translations for a language code
81
+ * Falls back to English if language is not supported
82
+ */
83
+ declare function getTranslations(langCode?: string): Translations;
84
+ /**
85
+ * Check if a language is supported
86
+ */
87
+ declare function isLanguageSupported(langCode?: string): boolean;
88
+
55
89
  interface WorkspaceContextValue {
56
90
  workspace: Workspace | null;
57
91
  drawings: Drawing[];
58
92
  activeDrawing: Drawing | null;
59
93
  isLoading: boolean;
60
94
  error: string | null;
95
+ lang: string;
96
+ t: Translations;
61
97
  createNewDrawing: (name?: string) => Promise<Drawing | null>;
62
98
  switchDrawing: (id: string) => Promise<void>;
63
99
  renameDrawing: (id: string, name: string) => Promise<void>;
@@ -66,10 +102,24 @@ interface WorkspaceContextValue {
66
102
  saveCurrentDrawing: (elements: unknown[], appState: Record<string, unknown>) => Promise<void>;
67
103
  }
68
104
  declare function useWorkspace(): WorkspaceContextValue;
105
+ /**
106
+ * Hook to get current language and translations
107
+ * Can be used by any component within WorkspaceProvider
108
+ */
109
+ declare function useWorkspaceLang(): {
110
+ lang: string;
111
+ t: Translations;
112
+ };
69
113
  interface WorkspaceProviderProps {
70
114
  children: ReactNode;
115
+ /**
116
+ * Language code (e.g., 'sv', 'en', 'sv-SE')
117
+ * Pass Excalidraw's langCode here to sync languages
118
+ * Falls back to English if not supported
119
+ */
120
+ lang?: string;
71
121
  }
72
- declare function WorkspaceProvider({ children }: WorkspaceProviderProps): react_jsx_runtime.JSX.Element;
122
+ declare function WorkspaceProvider({ children, lang }: WorkspaceProviderProps): react_jsx_runtime.JSX.Element;
73
123
 
74
124
  interface SidebarProps {
75
125
  isOpen?: boolean;
@@ -98,6 +148,11 @@ declare function DrawingListItem({ drawing, isActive, onSelect, onRename, onDele
98
148
  */
99
149
 
100
150
  interface WorkspaceMenuItemsProps {
151
+ /**
152
+ * Language code (e.g., 'sv', 'en', 'sv-SE')
153
+ * Falls back to English if not supported
154
+ */
155
+ lang?: string;
101
156
  /**
102
157
  * Called when a drawing is selected from the submenu
103
158
  */
@@ -137,6 +192,7 @@ interface WorkspaceMenuItemsProps {
137
192
  * <MainMenu.DefaultItems.SaveToActiveFile />
138
193
  * <MainMenu.Separator />
139
194
  * <WorkspaceMenuItems
195
+ * lang="sv"
140
196
  * renderMenuItem={(props) => <MainMenu.Item {...props} />}
141
197
  * renderSubMenu={(props) => <MainMenu.Sub>{props.children}</MainMenu.Sub>}
142
198
  * renderSeparator={() => <MainMenu.Separator />}
@@ -166,6 +222,11 @@ interface DrawingsDialogProps {
166
222
  * Called when a drawing is selected
167
223
  */
168
224
  onDrawingSelect?: (drawing: Drawing) => void;
225
+ /**
226
+ * Language code (e.g., 'sv', 'en', 'sv-SE')
227
+ * Falls back to English if not supported
228
+ */
229
+ lang?: string;
169
230
  }
170
231
  /**
171
232
  * DrawingsDialog - modal for managing workspace drawings
@@ -224,4 +285,4 @@ interface WorkspacePluginProps {
224
285
  */
225
286
  declare function WorkspacePlugin(props: WorkspacePluginProps): react_jsx_runtime.JSX.Element;
226
287
 
227
- export { type Drawing, DrawingList, DrawingListItem, DrawingsDialog, type DrawingsDialogProps, Sidebar, type Workspace, type WorkspaceContextValue, WorkspaceMenuItems, type WorkspaceMenuItemsProps, WorkspacePlugin, WorkspaceProvider, addDrawingToWorkspace, closeDB, createDrawing, deleteDrawing, duplicateDrawing, getAllDrawings, getDB, getDrawing, getOrCreateDefaultWorkspace, getWorkspace, removeDrawingFromWorkspace, setActiveDrawing, updateDrawing, updateWorkspace, useExcalidrawBridge, useWorkspace };
288
+ export { type Drawing, DrawingList, DrawingListItem, DrawingsDialog, type DrawingsDialogProps, Sidebar, type SupportedLanguage, type Translations, type Workspace, type WorkspaceContextValue, WorkspaceMenuItems, type WorkspaceMenuItemsProps, WorkspacePlugin, WorkspaceProvider, addDrawingToWorkspace, closeDB, createDrawing, deleteDrawing, duplicateDrawing, getAllDrawings, getDB, getDrawing, getOrCreateDefaultWorkspace, getTranslations, getWorkspace, isLanguageSupported, removeDrawingFromWorkspace, setActiveDrawing, updateDrawing, updateWorkspace, useExcalidrawBridge, useWorkspace, useWorkspaceLang };
package/dist/index.d.ts CHANGED
@@ -52,12 +52,48 @@ declare function addDrawingToWorkspace(workspaceId: string, drawingId: string):
52
52
  declare function removeDrawingFromWorkspace(workspaceId: string, drawingId: string): Promise<Workspace | undefined>;
53
53
  declare function setActiveDrawing(workspaceId: string, drawingId: string): Promise<Workspace | undefined>;
54
54
 
55
+ /**
56
+ * Rita Workspace Translations
57
+ *
58
+ * Supports Swedish (sv) and English (en)
59
+ */
60
+ type SupportedLanguage = 'sv' | 'en';
61
+ interface Translations {
62
+ drawings: string;
63
+ newDrawing: string;
64
+ manageDrawings: string;
65
+ dialogTitle: string;
66
+ close: string;
67
+ open: string;
68
+ rename: string;
69
+ delete: string;
70
+ save: string;
71
+ cancel: string;
72
+ confirm: string;
73
+ noDrawingsYet: string;
74
+ clickNewToStart: string;
75
+ modified: string;
76
+ confirmDelete: string;
77
+ shortcutNewDrawing: string;
78
+ }
79
+ /**
80
+ * Get translations for a language code
81
+ * Falls back to English if language is not supported
82
+ */
83
+ declare function getTranslations(langCode?: string): Translations;
84
+ /**
85
+ * Check if a language is supported
86
+ */
87
+ declare function isLanguageSupported(langCode?: string): boolean;
88
+
55
89
  interface WorkspaceContextValue {
56
90
  workspace: Workspace | null;
57
91
  drawings: Drawing[];
58
92
  activeDrawing: Drawing | null;
59
93
  isLoading: boolean;
60
94
  error: string | null;
95
+ lang: string;
96
+ t: Translations;
61
97
  createNewDrawing: (name?: string) => Promise<Drawing | null>;
62
98
  switchDrawing: (id: string) => Promise<void>;
63
99
  renameDrawing: (id: string, name: string) => Promise<void>;
@@ -66,10 +102,24 @@ interface WorkspaceContextValue {
66
102
  saveCurrentDrawing: (elements: unknown[], appState: Record<string, unknown>) => Promise<void>;
67
103
  }
68
104
  declare function useWorkspace(): WorkspaceContextValue;
105
+ /**
106
+ * Hook to get current language and translations
107
+ * Can be used by any component within WorkspaceProvider
108
+ */
109
+ declare function useWorkspaceLang(): {
110
+ lang: string;
111
+ t: Translations;
112
+ };
69
113
  interface WorkspaceProviderProps {
70
114
  children: ReactNode;
115
+ /**
116
+ * Language code (e.g., 'sv', 'en', 'sv-SE')
117
+ * Pass Excalidraw's langCode here to sync languages
118
+ * Falls back to English if not supported
119
+ */
120
+ lang?: string;
71
121
  }
72
- declare function WorkspaceProvider({ children }: WorkspaceProviderProps): react_jsx_runtime.JSX.Element;
122
+ declare function WorkspaceProvider({ children, lang }: WorkspaceProviderProps): react_jsx_runtime.JSX.Element;
73
123
 
74
124
  interface SidebarProps {
75
125
  isOpen?: boolean;
@@ -98,6 +148,11 @@ declare function DrawingListItem({ drawing, isActive, onSelect, onRename, onDele
98
148
  */
99
149
 
100
150
  interface WorkspaceMenuItemsProps {
151
+ /**
152
+ * Language code (e.g., 'sv', 'en', 'sv-SE')
153
+ * Falls back to English if not supported
154
+ */
155
+ lang?: string;
101
156
  /**
102
157
  * Called when a drawing is selected from the submenu
103
158
  */
@@ -137,6 +192,7 @@ interface WorkspaceMenuItemsProps {
137
192
  * <MainMenu.DefaultItems.SaveToActiveFile />
138
193
  * <MainMenu.Separator />
139
194
  * <WorkspaceMenuItems
195
+ * lang="sv"
140
196
  * renderMenuItem={(props) => <MainMenu.Item {...props} />}
141
197
  * renderSubMenu={(props) => <MainMenu.Sub>{props.children}</MainMenu.Sub>}
142
198
  * renderSeparator={() => <MainMenu.Separator />}
@@ -166,6 +222,11 @@ interface DrawingsDialogProps {
166
222
  * Called when a drawing is selected
167
223
  */
168
224
  onDrawingSelect?: (drawing: Drawing) => void;
225
+ /**
226
+ * Language code (e.g., 'sv', 'en', 'sv-SE')
227
+ * Falls back to English if not supported
228
+ */
229
+ lang?: string;
169
230
  }
170
231
  /**
171
232
  * DrawingsDialog - modal for managing workspace drawings
@@ -224,4 +285,4 @@ interface WorkspacePluginProps {
224
285
  */
225
286
  declare function WorkspacePlugin(props: WorkspacePluginProps): react_jsx_runtime.JSX.Element;
226
287
 
227
- export { type Drawing, DrawingList, DrawingListItem, DrawingsDialog, type DrawingsDialogProps, Sidebar, type Workspace, type WorkspaceContextValue, WorkspaceMenuItems, type WorkspaceMenuItemsProps, WorkspacePlugin, WorkspaceProvider, addDrawingToWorkspace, closeDB, createDrawing, deleteDrawing, duplicateDrawing, getAllDrawings, getDB, getDrawing, getOrCreateDefaultWorkspace, getWorkspace, removeDrawingFromWorkspace, setActiveDrawing, updateDrawing, updateWorkspace, useExcalidrawBridge, useWorkspace };
288
+ export { type Drawing, DrawingList, DrawingListItem, DrawingsDialog, type DrawingsDialogProps, Sidebar, type SupportedLanguage, type Translations, type Workspace, type WorkspaceContextValue, WorkspaceMenuItems, type WorkspaceMenuItemsProps, WorkspacePlugin, WorkspaceProvider, addDrawingToWorkspace, closeDB, createDrawing, deleteDrawing, duplicateDrawing, getAllDrawings, getDB, getDrawing, getOrCreateDefaultWorkspace, getTranslations, getWorkspace, isLanguageSupported, removeDrawingFromWorkspace, setActiveDrawing, updateDrawing, updateWorkspace, useExcalidrawBridge, useWorkspace, useWorkspaceLang };
package/dist/index.js CHANGED
@@ -46,13 +46,16 @@ __export(index_exports, {
46
46
  getDB: () => getDB,
47
47
  getDrawing: () => getDrawing,
48
48
  getOrCreateDefaultWorkspace: () => getOrCreateDefaultWorkspace,
49
+ getTranslations: () => getTranslations,
49
50
  getWorkspace: () => getWorkspace,
51
+ isLanguageSupported: () => isLanguageSupported,
50
52
  removeDrawingFromWorkspace: () => removeDrawingFromWorkspace,
51
53
  setActiveDrawing: () => setActiveDrawing,
52
54
  updateDrawing: () => updateDrawing,
53
55
  updateWorkspace: () => updateWorkspace,
54
56
  useExcalidrawBridge: () => useExcalidrawBridge,
55
- useWorkspace: () => useWorkspace
57
+ useWorkspace: () => useWorkspace,
58
+ useWorkspaceLang: () => useWorkspaceLang
56
59
  });
57
60
  module.exports = __toCommonJS(index_exports);
58
61
 
@@ -204,6 +207,71 @@ async function setActiveDrawing(workspaceId, drawingId) {
204
207
 
205
208
  // src/state/WorkspaceContext.tsx
206
209
  var import_react = require("react");
210
+
211
+ // src/i18n/translations.ts
212
+ var sv = {
213
+ // Menu
214
+ drawings: "Ritningar",
215
+ newDrawing: "Ny ritning",
216
+ manageDrawings: "Hantera ritningar...",
217
+ // Dialog
218
+ dialogTitle: "Ritningar",
219
+ close: "St\xE4ng",
220
+ open: "\xD6ppna",
221
+ rename: "Byt namn",
222
+ delete: "Ta bort",
223
+ save: "Spara",
224
+ cancel: "Avbryt",
225
+ confirm: "Bekr\xE4fta",
226
+ // Messages
227
+ noDrawingsYet: "Inga ritningar \xE4nnu.",
228
+ clickNewToStart: 'Klicka "Ny ritning" f\xF6r att b\xF6rja.',
229
+ modified: "\xC4ndrad",
230
+ confirmDelete: "Vill du ta bort denna ritning?",
231
+ // Shortcuts
232
+ shortcutNewDrawing: "Ctrl+Alt+N"
233
+ };
234
+ var en = {
235
+ // Menu
236
+ drawings: "Drawings",
237
+ newDrawing: "New drawing",
238
+ manageDrawings: "Manage drawings...",
239
+ // Dialog
240
+ dialogTitle: "Drawings",
241
+ close: "Close",
242
+ open: "Open",
243
+ rename: "Rename",
244
+ delete: "Delete",
245
+ save: "Save",
246
+ cancel: "Cancel",
247
+ confirm: "Confirm",
248
+ // Messages
249
+ noDrawingsYet: "No drawings yet.",
250
+ clickNewToStart: 'Click "New drawing" to start.',
251
+ modified: "Modified",
252
+ confirmDelete: "Do you want to delete this drawing?",
253
+ // Shortcuts
254
+ shortcutNewDrawing: "Ctrl+Alt+N"
255
+ };
256
+ var translations = {
257
+ sv,
258
+ en
259
+ };
260
+ function getTranslations(langCode) {
261
+ if (!langCode) return en;
262
+ const lang = langCode.split("-")[0].toLowerCase();
263
+ if (lang in translations) {
264
+ return translations[lang];
265
+ }
266
+ return en;
267
+ }
268
+ function isLanguageSupported(langCode) {
269
+ if (!langCode) return false;
270
+ const lang = langCode.split("-")[0].toLowerCase();
271
+ return lang in translations;
272
+ }
273
+
274
+ // src/state/WorkspaceContext.tsx
207
275
  var import_jsx_runtime = require("react/jsx-runtime");
208
276
  var WorkspaceContext = (0, import_react.createContext)(null);
209
277
  function useWorkspace() {
@@ -213,12 +281,20 @@ function useWorkspace() {
213
281
  }
214
282
  return context;
215
283
  }
216
- function WorkspaceProvider({ children }) {
284
+ function useWorkspaceLang() {
285
+ const context = (0, import_react.useContext)(WorkspaceContext);
286
+ if (!context) {
287
+ return { lang: "en", t: getTranslations("en") };
288
+ }
289
+ return { lang: context.lang, t: context.t };
290
+ }
291
+ function WorkspaceProvider({ children, lang = "en" }) {
217
292
  const [workspace, setWorkspace] = (0, import_react.useState)(null);
218
293
  const [drawings, setDrawings] = (0, import_react.useState)([]);
219
294
  const [activeDrawing, setActiveDrawing2] = (0, import_react.useState)(null);
220
295
  const [isLoading, setIsLoading] = (0, import_react.useState)(true);
221
296
  const [error, setError] = (0, import_react.useState)(null);
297
+ const t = getTranslations(lang);
222
298
  (0, import_react.useEffect)(() => {
223
299
  async function init() {
224
300
  try {
@@ -243,7 +319,8 @@ function WorkspaceProvider({ children }) {
243
319
  const createNewDrawing = (0, import_react.useCallback)(async (name) => {
244
320
  if (!workspace) return null;
245
321
  try {
246
- const drawing = await createDrawing(name || `Ritning ${drawings.length + 1}`);
322
+ const defaultName = `${t.newDrawing} ${drawings.length + 1}`;
323
+ const drawing = await createDrawing(name || defaultName);
247
324
  await addDrawingToWorkspace(workspace.id, drawing.id);
248
325
  await setActiveDrawing(workspace.id, drawing.id);
249
326
  setDrawings((prev) => [...prev, drawing]);
@@ -258,7 +335,7 @@ function WorkspaceProvider({ children }) {
258
335
  setError(err instanceof Error ? err.message : "Failed to create drawing");
259
336
  return null;
260
337
  }
261
- }, [workspace, drawings.length]);
338
+ }, [workspace, drawings.length, t]);
262
339
  const switchDrawing = (0, import_react.useCallback)(async (id) => {
263
340
  if (!workspace) return;
264
341
  try {
@@ -339,6 +416,8 @@ function WorkspaceProvider({ children }) {
339
416
  activeDrawing,
340
417
  isLoading,
341
418
  error,
419
+ lang,
420
+ t,
342
421
  createNewDrawing,
343
422
  switchDrawing,
344
423
  renameDrawing,
@@ -579,13 +658,15 @@ var DefaultMenuItem = ({ icon, children, onSelect, shortcut }) => /* @__PURE__ *
579
658
  }
580
659
  );
581
660
  var WorkspaceMenuItems = ({
661
+ lang,
582
662
  onDrawingSelect,
583
663
  onManageDrawings,
584
664
  renderMenuItem,
585
665
  renderSubMenu,
586
666
  renderSeparator
587
667
  }) => {
588
- const { drawings, activeDrawing, switchDrawing, createNewDrawing } = useWorkspace();
668
+ const { drawings, activeDrawing, switchDrawing, createNewDrawing, t: contextT, lang: contextLang } = useWorkspace();
669
+ const t = lang ? getTranslations(lang) : contextT;
589
670
  const MenuItem = renderMenuItem || ((props) => /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(DefaultMenuItem, { ...props }));
590
671
  const Separator = renderSeparator || (() => /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("hr", { style: { margin: "4px 0", border: "none", borderTop: "1px solid #ccc" } }));
591
672
  const handleDrawingSelect = async (drawing) => {
@@ -600,7 +681,8 @@ var WorkspaceMenuItems = ({
600
681
  trigger: /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_jsx_runtime5.Fragment, { children: [
601
682
  DrawingsIcon,
602
683
  /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("span", { children: [
603
- "Ritningar (",
684
+ t.drawings,
685
+ " (",
604
686
  drawings.length,
605
687
  ")"
606
688
  ] })
@@ -614,13 +696,13 @@ var WorkspaceMenuItems = ({
614
696
  drawings.length > 0 && Separator(),
615
697
  MenuItem({
616
698
  icon: PlusIcon,
617
- children: "Ny ritning",
699
+ children: t.newDrawing,
618
700
  onSelect: handleNewDrawing,
619
- shortcut: "Ctrl+Alt+N"
701
+ shortcut: t.shortcutNewDrawing
620
702
  }),
621
703
  onManageDrawings && MenuItem({
622
704
  icon: DrawingsIcon,
623
- children: "Hantera ritningar...",
705
+ children: t.manageDrawings,
624
706
  onSelect: onManageDrawings
625
707
  })
626
708
  ] })
@@ -629,9 +711,9 @@ var WorkspaceMenuItems = ({
629
711
  return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_jsx_runtime5.Fragment, { children: [
630
712
  MenuItem({
631
713
  icon: PlusIcon,
632
- children: "Ny ritning",
714
+ children: t.newDrawing,
633
715
  onSelect: handleNewDrawing,
634
- shortcut: "Ctrl+Alt+N"
716
+ shortcut: t.shortcutNewDrawing
635
717
  }),
636
718
  drawings.slice(0, 5).map((drawing) => /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_react4.default.Fragment, { children: MenuItem({
637
719
  icon: activeDrawing?.id === drawing.id ? "\u2713" : DrawingsIcon,
@@ -642,7 +724,7 @@ var WorkspaceMenuItems = ({
642
724
  Separator(),
643
725
  MenuItem({
644
726
  icon: DrawingsIcon,
645
- children: `Alla ritningar (${drawings.length})...`,
727
+ children: `${t.drawings} (${drawings.length})...`,
646
728
  onSelect: onManageDrawings
647
729
  })
648
730
  ] })
@@ -655,7 +737,8 @@ var import_jsx_runtime6 = require("react/jsx-runtime");
655
737
  var DrawingsDialog = ({
656
738
  open,
657
739
  onClose,
658
- onDrawingSelect
740
+ onDrawingSelect,
741
+ lang
659
742
  }) => {
660
743
  const {
661
744
  drawings,
@@ -663,8 +746,12 @@ var DrawingsDialog = ({
663
746
  switchDrawing,
664
747
  createNewDrawing,
665
748
  renameDrawing,
666
- removeDrawing
749
+ removeDrawing,
750
+ t: contextT,
751
+ lang: contextLang
667
752
  } = useWorkspace();
753
+ const t = lang ? getTranslations(lang) : contextT;
754
+ const effectiveLang = lang || contextLang;
668
755
  const [editingId, setEditingId] = (0, import_react5.useState)(null);
669
756
  const [editName, setEditName] = (0, import_react5.useState)("");
670
757
  const [confirmDeleteId, setConfirmDeleteId] = (0, import_react5.useState)(null);
@@ -699,8 +786,14 @@ var DrawingsDialog = ({
699
786
  await removeDrawing(id);
700
787
  setConfirmDeleteId(null);
701
788
  }, [removeDrawing]);
789
+ const getLocale = () => {
790
+ if (!effectiveLang) return "en-US";
791
+ const baseLang = effectiveLang.split("-")[0].toLowerCase();
792
+ if (baseLang === "sv") return "sv-SE";
793
+ return "en-US";
794
+ };
702
795
  const formatDate = (timestamp) => {
703
- return new Date(timestamp).toLocaleString("sv-SE", {
796
+ return new Date(timestamp).toLocaleString(getLocale(), {
704
797
  year: "numeric",
705
798
  month: "short",
706
799
  day: "numeric",
@@ -756,7 +849,8 @@ var DrawingsDialog = ({
756
849
  },
757
850
  children: [
758
851
  /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("h2", { style: { margin: 0, fontSize: "18px", fontWeight: 600 }, children: [
759
- "Ritningar (",
852
+ t.dialogTitle,
853
+ " (",
760
854
  drawings.length,
761
855
  ")"
762
856
  ] }),
@@ -773,7 +867,7 @@ var DrawingsDialog = ({
773
867
  lineHeight: 1,
774
868
  color: "inherit"
775
869
  },
776
- "aria-label": "St\xE4ng",
870
+ "aria-label": t.close,
777
871
  children: "\xD7"
778
872
  }
779
873
  )
@@ -797,8 +891,8 @@ var DrawingsDialog = ({
797
891
  color: "var(--text-secondary-color, #666)"
798
892
  },
799
893
  children: [
800
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("p", { children: "Inga ritningar \xE4nnu." }),
801
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("p", { children: 'Klicka "Ny ritning" f\xF6r att b\xF6rja.' })
894
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("p", { children: t.noDrawingsYet }),
895
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("p", { children: t.clickNewToStart })
802
896
  ]
803
897
  }
804
898
  ) : drawings.map((drawing) => /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
@@ -860,7 +954,8 @@ var DrawingsDialog = ({
860
954
  marginTop: "2px"
861
955
  },
862
956
  children: [
863
- "\xC4ndrad: ",
957
+ t.modified,
958
+ ": ",
864
959
  formatDate(drawing.updatedAt)
865
960
  ]
866
961
  }
@@ -880,7 +975,7 @@ var DrawingsDialog = ({
880
975
  borderRadius: "4px",
881
976
  cursor: "pointer"
882
977
  },
883
- children: "Spara"
978
+ children: t.save
884
979
  }
885
980
  ),
886
981
  /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
@@ -896,7 +991,7 @@ var DrawingsDialog = ({
896
991
  cursor: "pointer",
897
992
  color: "inherit"
898
993
  },
899
- children: "Avbryt"
994
+ children: t.cancel
900
995
  }
901
996
  )
902
997
  ] }) : confirmDeleteId === drawing.id ? /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(import_jsx_runtime6.Fragment, { children: [
@@ -913,7 +1008,7 @@ var DrawingsDialog = ({
913
1008
  borderRadius: "4px",
914
1009
  cursor: "pointer"
915
1010
  },
916
- children: "Ta bort"
1011
+ children: t.delete
917
1012
  }
918
1013
  ),
919
1014
  /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
@@ -929,7 +1024,7 @@ var DrawingsDialog = ({
929
1024
  cursor: "pointer",
930
1025
  color: "inherit"
931
1026
  },
932
- children: "Avbryt"
1027
+ children: t.cancel
933
1028
  }
934
1029
  )
935
1030
  ] }) : /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(import_jsx_runtime6.Fragment, { children: [
@@ -947,7 +1042,7 @@ var DrawingsDialog = ({
947
1042
  cursor: "pointer"
948
1043
  },
949
1044
  disabled: activeDrawing?.id === drawing.id,
950
- children: "\xD6ppna"
1045
+ children: t.open
951
1046
  }
952
1047
  ),
953
1048
  /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
@@ -963,7 +1058,7 @@ var DrawingsDialog = ({
963
1058
  cursor: "pointer",
964
1059
  color: "inherit"
965
1060
  },
966
- title: "Byt namn",
1061
+ title: t.rename,
967
1062
  children: "\u270F\uFE0F"
968
1063
  }
969
1064
  ),
@@ -980,7 +1075,7 @@ var DrawingsDialog = ({
980
1075
  cursor: "pointer",
981
1076
  color: "inherit"
982
1077
  },
983
- title: "Ta bort",
1078
+ title: t.delete,
984
1079
  disabled: drawings.length <= 1,
985
1080
  children: "\u{1F5D1}\uFE0F"
986
1081
  }
@@ -1003,7 +1098,7 @@ var DrawingsDialog = ({
1003
1098
  alignItems: "center"
1004
1099
  },
1005
1100
  children: [
1006
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
1101
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
1007
1102
  "button",
1008
1103
  {
1009
1104
  onClick: handleCreate,
@@ -1017,7 +1112,10 @@ var DrawingsDialog = ({
1017
1112
  cursor: "pointer",
1018
1113
  fontWeight: 500
1019
1114
  },
1020
- children: "+ Ny ritning"
1115
+ children: [
1116
+ "+ ",
1117
+ t.newDrawing
1118
+ ]
1021
1119
  }
1022
1120
  ),
1023
1121
  /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
@@ -1033,7 +1131,7 @@ var DrawingsDialog = ({
1033
1131
  cursor: "pointer",
1034
1132
  color: "inherit"
1035
1133
  },
1036
- children: "St\xE4ng"
1134
+ children: t.close
1037
1135
  }
1038
1136
  )
1039
1137
  ]
@@ -1166,11 +1264,14 @@ function WorkspacePlugin(props) {
1166
1264
  getDB,
1167
1265
  getDrawing,
1168
1266
  getOrCreateDefaultWorkspace,
1267
+ getTranslations,
1169
1268
  getWorkspace,
1269
+ isLanguageSupported,
1170
1270
  removeDrawingFromWorkspace,
1171
1271
  setActiveDrawing,
1172
1272
  updateDrawing,
1173
1273
  updateWorkspace,
1174
1274
  useExcalidrawBridge,
1175
- useWorkspace
1275
+ useWorkspace,
1276
+ useWorkspaceLang
1176
1277
  });
package/dist/index.mjs CHANGED
@@ -146,6 +146,71 @@ async function setActiveDrawing(workspaceId, drawingId) {
146
146
 
147
147
  // src/state/WorkspaceContext.tsx
148
148
  import { createContext, useContext, useEffect, useState, useCallback } from "react";
149
+
150
+ // src/i18n/translations.ts
151
+ var sv = {
152
+ // Menu
153
+ drawings: "Ritningar",
154
+ newDrawing: "Ny ritning",
155
+ manageDrawings: "Hantera ritningar...",
156
+ // Dialog
157
+ dialogTitle: "Ritningar",
158
+ close: "St\xE4ng",
159
+ open: "\xD6ppna",
160
+ rename: "Byt namn",
161
+ delete: "Ta bort",
162
+ save: "Spara",
163
+ cancel: "Avbryt",
164
+ confirm: "Bekr\xE4fta",
165
+ // Messages
166
+ noDrawingsYet: "Inga ritningar \xE4nnu.",
167
+ clickNewToStart: 'Klicka "Ny ritning" f\xF6r att b\xF6rja.',
168
+ modified: "\xC4ndrad",
169
+ confirmDelete: "Vill du ta bort denna ritning?",
170
+ // Shortcuts
171
+ shortcutNewDrawing: "Ctrl+Alt+N"
172
+ };
173
+ var en = {
174
+ // Menu
175
+ drawings: "Drawings",
176
+ newDrawing: "New drawing",
177
+ manageDrawings: "Manage drawings...",
178
+ // Dialog
179
+ dialogTitle: "Drawings",
180
+ close: "Close",
181
+ open: "Open",
182
+ rename: "Rename",
183
+ delete: "Delete",
184
+ save: "Save",
185
+ cancel: "Cancel",
186
+ confirm: "Confirm",
187
+ // Messages
188
+ noDrawingsYet: "No drawings yet.",
189
+ clickNewToStart: 'Click "New drawing" to start.',
190
+ modified: "Modified",
191
+ confirmDelete: "Do you want to delete this drawing?",
192
+ // Shortcuts
193
+ shortcutNewDrawing: "Ctrl+Alt+N"
194
+ };
195
+ var translations = {
196
+ sv,
197
+ en
198
+ };
199
+ function getTranslations(langCode) {
200
+ if (!langCode) return en;
201
+ const lang = langCode.split("-")[0].toLowerCase();
202
+ if (lang in translations) {
203
+ return translations[lang];
204
+ }
205
+ return en;
206
+ }
207
+ function isLanguageSupported(langCode) {
208
+ if (!langCode) return false;
209
+ const lang = langCode.split("-")[0].toLowerCase();
210
+ return lang in translations;
211
+ }
212
+
213
+ // src/state/WorkspaceContext.tsx
149
214
  import { jsx } from "react/jsx-runtime";
150
215
  var WorkspaceContext = createContext(null);
151
216
  function useWorkspace() {
@@ -155,12 +220,20 @@ function useWorkspace() {
155
220
  }
156
221
  return context;
157
222
  }
158
- function WorkspaceProvider({ children }) {
223
+ function useWorkspaceLang() {
224
+ const context = useContext(WorkspaceContext);
225
+ if (!context) {
226
+ return { lang: "en", t: getTranslations("en") };
227
+ }
228
+ return { lang: context.lang, t: context.t };
229
+ }
230
+ function WorkspaceProvider({ children, lang = "en" }) {
159
231
  const [workspace, setWorkspace] = useState(null);
160
232
  const [drawings, setDrawings] = useState([]);
161
233
  const [activeDrawing, setActiveDrawing2] = useState(null);
162
234
  const [isLoading, setIsLoading] = useState(true);
163
235
  const [error, setError] = useState(null);
236
+ const t = getTranslations(lang);
164
237
  useEffect(() => {
165
238
  async function init() {
166
239
  try {
@@ -185,7 +258,8 @@ function WorkspaceProvider({ children }) {
185
258
  const createNewDrawing = useCallback(async (name) => {
186
259
  if (!workspace) return null;
187
260
  try {
188
- const drawing = await createDrawing(name || `Ritning ${drawings.length + 1}`);
261
+ const defaultName = `${t.newDrawing} ${drawings.length + 1}`;
262
+ const drawing = await createDrawing(name || defaultName);
189
263
  await addDrawingToWorkspace(workspace.id, drawing.id);
190
264
  await setActiveDrawing(workspace.id, drawing.id);
191
265
  setDrawings((prev) => [...prev, drawing]);
@@ -200,7 +274,7 @@ function WorkspaceProvider({ children }) {
200
274
  setError(err instanceof Error ? err.message : "Failed to create drawing");
201
275
  return null;
202
276
  }
203
- }, [workspace, drawings.length]);
277
+ }, [workspace, drawings.length, t]);
204
278
  const switchDrawing = useCallback(async (id) => {
205
279
  if (!workspace) return;
206
280
  try {
@@ -281,6 +355,8 @@ function WorkspaceProvider({ children }) {
281
355
  activeDrawing,
282
356
  isLoading,
283
357
  error,
358
+ lang,
359
+ t,
284
360
  createNewDrawing,
285
361
  switchDrawing,
286
362
  renameDrawing,
@@ -521,13 +597,15 @@ var DefaultMenuItem = ({ icon, children, onSelect, shortcut }) => /* @__PURE__ *
521
597
  }
522
598
  );
523
599
  var WorkspaceMenuItems = ({
600
+ lang,
524
601
  onDrawingSelect,
525
602
  onManageDrawings,
526
603
  renderMenuItem,
527
604
  renderSubMenu,
528
605
  renderSeparator
529
606
  }) => {
530
- const { drawings, activeDrawing, switchDrawing, createNewDrawing } = useWorkspace();
607
+ const { drawings, activeDrawing, switchDrawing, createNewDrawing, t: contextT, lang: contextLang } = useWorkspace();
608
+ const t = lang ? getTranslations(lang) : contextT;
531
609
  const MenuItem = renderMenuItem || ((props) => /* @__PURE__ */ jsx5(DefaultMenuItem, { ...props }));
532
610
  const Separator = renderSeparator || (() => /* @__PURE__ */ jsx5("hr", { style: { margin: "4px 0", border: "none", borderTop: "1px solid #ccc" } }));
533
611
  const handleDrawingSelect = async (drawing) => {
@@ -542,7 +620,8 @@ var WorkspaceMenuItems = ({
542
620
  trigger: /* @__PURE__ */ jsxs3(Fragment2, { children: [
543
621
  DrawingsIcon,
544
622
  /* @__PURE__ */ jsxs3("span", { children: [
545
- "Ritningar (",
623
+ t.drawings,
624
+ " (",
546
625
  drawings.length,
547
626
  ")"
548
627
  ] })
@@ -556,13 +635,13 @@ var WorkspaceMenuItems = ({
556
635
  drawings.length > 0 && Separator(),
557
636
  MenuItem({
558
637
  icon: PlusIcon,
559
- children: "Ny ritning",
638
+ children: t.newDrawing,
560
639
  onSelect: handleNewDrawing,
561
- shortcut: "Ctrl+Alt+N"
640
+ shortcut: t.shortcutNewDrawing
562
641
  }),
563
642
  onManageDrawings && MenuItem({
564
643
  icon: DrawingsIcon,
565
- children: "Hantera ritningar...",
644
+ children: t.manageDrawings,
566
645
  onSelect: onManageDrawings
567
646
  })
568
647
  ] })
@@ -571,9 +650,9 @@ var WorkspaceMenuItems = ({
571
650
  return /* @__PURE__ */ jsxs3(Fragment2, { children: [
572
651
  MenuItem({
573
652
  icon: PlusIcon,
574
- children: "Ny ritning",
653
+ children: t.newDrawing,
575
654
  onSelect: handleNewDrawing,
576
- shortcut: "Ctrl+Alt+N"
655
+ shortcut: t.shortcutNewDrawing
577
656
  }),
578
657
  drawings.slice(0, 5).map((drawing) => /* @__PURE__ */ jsx5(React4.Fragment, { children: MenuItem({
579
658
  icon: activeDrawing?.id === drawing.id ? "\u2713" : DrawingsIcon,
@@ -584,7 +663,7 @@ var WorkspaceMenuItems = ({
584
663
  Separator(),
585
664
  MenuItem({
586
665
  icon: DrawingsIcon,
587
- children: `Alla ritningar (${drawings.length})...`,
666
+ children: `${t.drawings} (${drawings.length})...`,
588
667
  onSelect: onManageDrawings
589
668
  })
590
669
  ] })
@@ -592,12 +671,13 @@ var WorkspaceMenuItems = ({
592
671
  };
593
672
 
594
673
  // src/ui/Dialog/DrawingsDialog.tsx
595
- import { useState as useState5, useCallback as useCallback2 } from "react";
674
+ import { useState as useState4, useCallback as useCallback2 } from "react";
596
675
  import { Fragment as Fragment3, jsx as jsx6, jsxs as jsxs4 } from "react/jsx-runtime";
597
676
  var DrawingsDialog = ({
598
677
  open,
599
678
  onClose,
600
- onDrawingSelect
679
+ onDrawingSelect,
680
+ lang
601
681
  }) => {
602
682
  const {
603
683
  drawings,
@@ -605,11 +685,15 @@ var DrawingsDialog = ({
605
685
  switchDrawing,
606
686
  createNewDrawing,
607
687
  renameDrawing,
608
- removeDrawing
688
+ removeDrawing,
689
+ t: contextT,
690
+ lang: contextLang
609
691
  } = useWorkspace();
610
- const [editingId, setEditingId] = useState5(null);
611
- const [editName, setEditName] = useState5("");
612
- const [confirmDeleteId, setConfirmDeleteId] = useState5(null);
692
+ const t = lang ? getTranslations(lang) : contextT;
693
+ const effectiveLang = lang || contextLang;
694
+ const [editingId, setEditingId] = useState4(null);
695
+ const [editName, setEditName] = useState4("");
696
+ const [confirmDeleteId, setConfirmDeleteId] = useState4(null);
613
697
  const handleSelect = useCallback2(async (drawing) => {
614
698
  await switchDrawing(drawing.id);
615
699
  onDrawingSelect?.(drawing);
@@ -641,8 +725,14 @@ var DrawingsDialog = ({
641
725
  await removeDrawing(id);
642
726
  setConfirmDeleteId(null);
643
727
  }, [removeDrawing]);
728
+ const getLocale = () => {
729
+ if (!effectiveLang) return "en-US";
730
+ const baseLang = effectiveLang.split("-")[0].toLowerCase();
731
+ if (baseLang === "sv") return "sv-SE";
732
+ return "en-US";
733
+ };
644
734
  const formatDate = (timestamp) => {
645
- return new Date(timestamp).toLocaleString("sv-SE", {
735
+ return new Date(timestamp).toLocaleString(getLocale(), {
646
736
  year: "numeric",
647
737
  month: "short",
648
738
  day: "numeric",
@@ -698,7 +788,8 @@ var DrawingsDialog = ({
698
788
  },
699
789
  children: [
700
790
  /* @__PURE__ */ jsxs4("h2", { style: { margin: 0, fontSize: "18px", fontWeight: 600 }, children: [
701
- "Ritningar (",
791
+ t.dialogTitle,
792
+ " (",
702
793
  drawings.length,
703
794
  ")"
704
795
  ] }),
@@ -715,7 +806,7 @@ var DrawingsDialog = ({
715
806
  lineHeight: 1,
716
807
  color: "inherit"
717
808
  },
718
- "aria-label": "St\xE4ng",
809
+ "aria-label": t.close,
719
810
  children: "\xD7"
720
811
  }
721
812
  )
@@ -739,8 +830,8 @@ var DrawingsDialog = ({
739
830
  color: "var(--text-secondary-color, #666)"
740
831
  },
741
832
  children: [
742
- /* @__PURE__ */ jsx6("p", { children: "Inga ritningar \xE4nnu." }),
743
- /* @__PURE__ */ jsx6("p", { children: 'Klicka "Ny ritning" f\xF6r att b\xF6rja.' })
833
+ /* @__PURE__ */ jsx6("p", { children: t.noDrawingsYet }),
834
+ /* @__PURE__ */ jsx6("p", { children: t.clickNewToStart })
744
835
  ]
745
836
  }
746
837
  ) : drawings.map((drawing) => /* @__PURE__ */ jsxs4(
@@ -802,7 +893,8 @@ var DrawingsDialog = ({
802
893
  marginTop: "2px"
803
894
  },
804
895
  children: [
805
- "\xC4ndrad: ",
896
+ t.modified,
897
+ ": ",
806
898
  formatDate(drawing.updatedAt)
807
899
  ]
808
900
  }
@@ -822,7 +914,7 @@ var DrawingsDialog = ({
822
914
  borderRadius: "4px",
823
915
  cursor: "pointer"
824
916
  },
825
- children: "Spara"
917
+ children: t.save
826
918
  }
827
919
  ),
828
920
  /* @__PURE__ */ jsx6(
@@ -838,7 +930,7 @@ var DrawingsDialog = ({
838
930
  cursor: "pointer",
839
931
  color: "inherit"
840
932
  },
841
- children: "Avbryt"
933
+ children: t.cancel
842
934
  }
843
935
  )
844
936
  ] }) : confirmDeleteId === drawing.id ? /* @__PURE__ */ jsxs4(Fragment3, { children: [
@@ -855,7 +947,7 @@ var DrawingsDialog = ({
855
947
  borderRadius: "4px",
856
948
  cursor: "pointer"
857
949
  },
858
- children: "Ta bort"
950
+ children: t.delete
859
951
  }
860
952
  ),
861
953
  /* @__PURE__ */ jsx6(
@@ -871,7 +963,7 @@ var DrawingsDialog = ({
871
963
  cursor: "pointer",
872
964
  color: "inherit"
873
965
  },
874
- children: "Avbryt"
966
+ children: t.cancel
875
967
  }
876
968
  )
877
969
  ] }) : /* @__PURE__ */ jsxs4(Fragment3, { children: [
@@ -889,7 +981,7 @@ var DrawingsDialog = ({
889
981
  cursor: "pointer"
890
982
  },
891
983
  disabled: activeDrawing?.id === drawing.id,
892
- children: "\xD6ppna"
984
+ children: t.open
893
985
  }
894
986
  ),
895
987
  /* @__PURE__ */ jsx6(
@@ -905,7 +997,7 @@ var DrawingsDialog = ({
905
997
  cursor: "pointer",
906
998
  color: "inherit"
907
999
  },
908
- title: "Byt namn",
1000
+ title: t.rename,
909
1001
  children: "\u270F\uFE0F"
910
1002
  }
911
1003
  ),
@@ -922,7 +1014,7 @@ var DrawingsDialog = ({
922
1014
  cursor: "pointer",
923
1015
  color: "inherit"
924
1016
  },
925
- title: "Ta bort",
1017
+ title: t.delete,
926
1018
  disabled: drawings.length <= 1,
927
1019
  children: "\u{1F5D1}\uFE0F"
928
1020
  }
@@ -945,7 +1037,7 @@ var DrawingsDialog = ({
945
1037
  alignItems: "center"
946
1038
  },
947
1039
  children: [
948
- /* @__PURE__ */ jsx6(
1040
+ /* @__PURE__ */ jsxs4(
949
1041
  "button",
950
1042
  {
951
1043
  onClick: handleCreate,
@@ -959,7 +1051,10 @@ var DrawingsDialog = ({
959
1051
  cursor: "pointer",
960
1052
  fontWeight: 500
961
1053
  },
962
- children: "+ Ny ritning"
1054
+ children: [
1055
+ "+ ",
1056
+ t.newDrawing
1057
+ ]
963
1058
  }
964
1059
  ),
965
1060
  /* @__PURE__ */ jsx6(
@@ -975,7 +1070,7 @@ var DrawingsDialog = ({
975
1070
  cursor: "pointer",
976
1071
  color: "inherit"
977
1072
  },
978
- children: "St\xE4ng"
1073
+ children: t.close
979
1074
  }
980
1075
  )
981
1076
  ]
@@ -1030,14 +1125,14 @@ function useExcalidrawBridge({
1030
1125
  }
1031
1126
 
1032
1127
  // src/WorkspacePlugin.tsx
1033
- import { useState as useState6, useEffect as useEffect4, useCallback as useCallback4 } from "react";
1128
+ import { useState as useState5, useEffect as useEffect4, useCallback as useCallback4 } from "react";
1034
1129
  import { jsx as jsx7, jsxs as jsxs5 } from "react/jsx-runtime";
1035
1130
  function WorkspacePluginInner({
1036
1131
  children,
1037
1132
  defaultSidebarOpen = true,
1038
1133
  sidebarWidth = 250
1039
1134
  }) {
1040
- const [sidebarOpen, setSidebarOpen] = useState6(defaultSidebarOpen);
1135
+ const [sidebarOpen, setSidebarOpen] = useState5(defaultSidebarOpen);
1041
1136
  const { activeDrawing } = useWorkspace();
1042
1137
  useEffect4(() => {
1043
1138
  const handleKeyDown = (e) => {
@@ -1107,11 +1202,14 @@ export {
1107
1202
  getDB,
1108
1203
  getDrawing,
1109
1204
  getOrCreateDefaultWorkspace,
1205
+ getTranslations,
1110
1206
  getWorkspace,
1207
+ isLanguageSupported,
1111
1208
  removeDrawingFromWorkspace,
1112
1209
  setActiveDrawing,
1113
1210
  updateDrawing,
1114
1211
  updateWorkspace,
1115
1212
  useExcalidrawBridge,
1116
- useWorkspace
1213
+ useWorkspace,
1214
+ useWorkspaceLang
1117
1215
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "rita-workspace",
3
- "version": "0.2.1",
3
+ "version": "0.3.1",
4
4
  "description": "Multi-drawing workspace feature for Rita (Excalidraw fork)",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.mjs",