@elixpo/lixsketch 5.4.7 → 5.5.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.
Files changed (218) hide show
  1. package/dist/react/AIRenderer-M4LMJ66J.js +1105 -0
  2. package/dist/react/AIRenderer-M4LMJ66J.js.map +7 -0
  3. package/dist/react/Arrow-BJDAXPMH.js +8 -0
  4. package/dist/react/Arrow-BJDAXPMH.js.map +7 -0
  5. package/dist/react/Circle-KPG7TKIX.js +8 -0
  6. package/dist/react/Circle-KPG7TKIX.js.map +7 -0
  7. package/dist/react/CodeShape-K4DIZAIV.js +8 -0
  8. package/dist/react/CodeShape-K4DIZAIV.js.map +7 -0
  9. package/dist/react/CopyPaste-4CKJRHJ3.js +569 -0
  10. package/dist/react/CopyPaste-4CKJRHJ3.js.map +7 -0
  11. package/dist/react/EraserTrail-PA6IQLQN.js +20 -0
  12. package/dist/react/EraserTrail-PA6IQLQN.js.map +7 -0
  13. package/dist/react/EventDispatcher-SRFH6LQZ.js +463 -0
  14. package/dist/react/EventDispatcher-SRFH6LQZ.js.map +7 -0
  15. package/dist/react/Frame-6UR5XPAX.js +10 -0
  16. package/dist/react/Frame-6UR5XPAX.js.map +7 -0
  17. package/dist/react/FreehandStroke-CK24NUT3.js +8 -0
  18. package/dist/react/FreehandStroke-CK24NUT3.js.map +7 -0
  19. package/dist/react/GraphEngine-QE5B2PMR.js +340 -0
  20. package/dist/react/GraphEngine-QE5B2PMR.js.map +7 -0
  21. package/dist/react/GraphMathParser-2WMTY4IE.js +10 -0
  22. package/dist/react/GraphMathParser-2WMTY4IE.js.map +7 -0
  23. package/dist/react/IconShape-KMIA6T2H.js +10 -0
  24. package/dist/react/IconShape-KMIA6T2H.js.map +7 -0
  25. package/dist/react/ImageShape-CHHGBXUQ.js +10 -0
  26. package/dist/react/ImageShape-CHHGBXUQ.js.map +7 -0
  27. package/dist/react/LayerOrder-XCHF4MSS.js +66 -0
  28. package/dist/react/LayerOrder-XCHF4MSS.js.map +7 -0
  29. package/dist/react/Line-2KOQEEGA.js +10 -0
  30. package/dist/react/Line-2KOQEEGA.js.map +7 -0
  31. package/dist/react/LixScriptParser-JYWJX375.js +1033 -0
  32. package/dist/react/LixScriptParser-JYWJX375.js.map +7 -0
  33. package/dist/react/MermaidFlowchartRenderer-4QBAZ5MB.js +412 -0
  34. package/dist/react/MermaidFlowchartRenderer-4QBAZ5MB.js.map +7 -0
  35. package/dist/react/MermaidSequenceParser-UKG2NSZY.js +8 -0
  36. package/dist/react/MermaidSequenceParser-UKG2NSZY.js.map +7 -0
  37. package/dist/react/MermaidSequenceRenderer-HPLHY5II.js +387 -0
  38. package/dist/react/MermaidSequenceRenderer-HPLHY5II.js.map +7 -0
  39. package/dist/react/Rectangle-6FE7RN6W.js +8 -0
  40. package/dist/react/Rectangle-6FE7RN6W.js.map +7 -0
  41. package/dist/react/ResizeCode-WAMDTKSW.js +2 -0
  42. package/dist/react/ResizeCode-WAMDTKSW.js.map +7 -0
  43. package/dist/react/ResizeShapes-LKEQTITP.js +250 -0
  44. package/dist/react/ResizeShapes-LKEQTITP.js.map +7 -0
  45. package/dist/react/SceneSerializer-4U4B24JM.js +739 -0
  46. package/dist/react/SceneSerializer-4U4B24JM.js.map +7 -0
  47. package/dist/react/Selection-VVUHY5YJ.js +34 -0
  48. package/dist/react/Selection-VVUHY5YJ.js.map +7 -0
  49. package/dist/react/SketchEngine-YA4RG3KX.js +413 -0
  50. package/dist/react/SketchEngine-YA4RG3KX.js.map +7 -0
  51. package/dist/react/TextShape-54ZJ66E3.js +8 -0
  52. package/dist/react/TextShape-54ZJ66E3.js.map +7 -0
  53. package/dist/react/UndoRedo-M2JZUBKN.js +30 -0
  54. package/dist/react/UndoRedo-M2JZUBKN.js.map +7 -0
  55. package/dist/react/ZoomPan-U3TXC5AJ.js +186 -0
  56. package/dist/react/ZoomPan-U3TXC5AJ.js.map +7 -0
  57. package/dist/react/arrowTool-CWEMIRXK.js +17 -0
  58. package/dist/react/arrowTool-CWEMIRXK.js.map +7 -0
  59. package/dist/react/boxicons-5JNJQPUP.woff +0 -0
  60. package/dist/react/boxicons-6NVWQSCQ.eot +0 -0
  61. package/dist/react/boxicons-AQ5N6WP7.woff2 +0 -0
  62. package/dist/react/boxicons-GDR4JU3X.ttf +0 -0
  63. package/dist/react/boxicons-NNFHLMOR.svg +1660 -0
  64. package/dist/react/chunk-2OQXI7QB.js +564 -0
  65. package/dist/react/chunk-2OQXI7QB.js.map +7 -0
  66. package/dist/react/chunk-5OUBTHHO.js +187 -0
  67. package/dist/react/chunk-5OUBTHHO.js.map +7 -0
  68. package/dist/react/chunk-6PFXZKL2.js +628 -0
  69. package/dist/react/chunk-6PFXZKL2.js.map +7 -0
  70. package/dist/react/chunk-6SFNWGGZ.js +453 -0
  71. package/dist/react/chunk-6SFNWGGZ.js.map +7 -0
  72. package/dist/react/chunk-7TZSIR6V.js +210 -0
  73. package/dist/react/chunk-7TZSIR6V.js.map +7 -0
  74. package/dist/react/chunk-AJAZC37E.js +662 -0
  75. package/dist/react/chunk-AJAZC37E.js.map +7 -0
  76. package/dist/react/chunk-BU4D2WYQ.js +1213 -0
  77. package/dist/react/chunk-BU4D2WYQ.js.map +7 -0
  78. package/dist/react/chunk-BZE4CEBG.js +747 -0
  79. package/dist/react/chunk-BZE4CEBG.js.map +7 -0
  80. package/dist/react/chunk-CB2RANCB.js +212 -0
  81. package/dist/react/chunk-CB2RANCB.js.map +7 -0
  82. package/dist/react/chunk-DNAG7ML6.js +128 -0
  83. package/dist/react/chunk-DNAG7ML6.js.map +7 -0
  84. package/dist/react/chunk-HZWLPXFN.js +198 -0
  85. package/dist/react/chunk-HZWLPXFN.js.map +7 -0
  86. package/dist/react/chunk-I6HCCIXB.js +572 -0
  87. package/dist/react/chunk-I6HCCIXB.js.map +7 -0
  88. package/dist/react/chunk-IZ5OGWGW.js +235 -0
  89. package/dist/react/chunk-IZ5OGWGW.js.map +7 -0
  90. package/dist/react/chunk-JJCJNLNN.js +1490 -0
  91. package/dist/react/chunk-JJCJNLNN.js.map +7 -0
  92. package/dist/react/chunk-JQ3IRFDP.js +222 -0
  93. package/dist/react/chunk-JQ3IRFDP.js.map +7 -0
  94. package/dist/react/chunk-L5OARZJ7.js +1134 -0
  95. package/dist/react/chunk-L5OARZJ7.js.map +7 -0
  96. package/dist/react/chunk-LHRTXNVE.js +1600 -0
  97. package/dist/react/chunk-LHRTXNVE.js.map +7 -0
  98. package/dist/react/chunk-Q2GA4MBZ.js +1653 -0
  99. package/dist/react/chunk-Q2GA4MBZ.js.map +7 -0
  100. package/dist/react/chunk-QNSE5BAY.js +519 -0
  101. package/dist/react/chunk-QNSE5BAY.js.map +7 -0
  102. package/dist/react/chunk-QXFBG7OM.js +191 -0
  103. package/dist/react/chunk-QXFBG7OM.js.map +7 -0
  104. package/dist/react/chunk-T6ZVV5ZO.js +714 -0
  105. package/dist/react/chunk-T6ZVV5ZO.js.map +7 -0
  106. package/dist/react/chunk-URB6MY46.js +974 -0
  107. package/dist/react/chunk-URB6MY46.js.map +7 -0
  108. package/dist/react/chunk-VN62KLOC.js +931 -0
  109. package/dist/react/chunk-VN62KLOC.js.map +7 -0
  110. package/dist/react/chunk-VQVEPJSA.js +158 -0
  111. package/dist/react/chunk-VQVEPJSA.js.map +7 -0
  112. package/dist/react/chunk-XISEAGBV.js +1632 -0
  113. package/dist/react/chunk-XISEAGBV.js.map +7 -0
  114. package/dist/react/chunk-YKJUBFHE.js +575 -0
  115. package/dist/react/chunk-YKJUBFHE.js.map +7 -0
  116. package/dist/react/circleTool-NUATSEI2.js +14 -0
  117. package/dist/react/circleTool-NUATSEI2.js.map +7 -0
  118. package/dist/react/codeTool-MHCB2FNB.js +38 -0
  119. package/dist/react/codeTool-MHCB2FNB.js.map +7 -0
  120. package/dist/react/eraserTool-2GS2LQCS.js +103 -0
  121. package/dist/react/eraserTool-2GS2LQCS.js.map +7 -0
  122. package/dist/react/frameTool-PWVKKXSP.js +14 -0
  123. package/dist/react/frameTool-PWVKKXSP.js.map +7 -0
  124. package/dist/react/freehandTool-SLYGASVP.js +14 -0
  125. package/dist/react/freehandTool-SLYGASVP.js.map +7 -0
  126. package/dist/react/iconTool-GPZ7O7NH.js +18 -0
  127. package/dist/react/iconTool-GPZ7O7NH.js.map +7 -0
  128. package/dist/react/imageTool-D5R4XGEU.js +15 -0
  129. package/dist/react/imageTool-D5R4XGEU.js.map +7 -0
  130. package/dist/react/index.js +5349 -0
  131. package/dist/react/index.js.map +7 -0
  132. package/dist/react/laserTool-XVMV63AV.js +239 -0
  133. package/dist/react/laserTool-XVMV63AV.js.map +7 -0
  134. package/dist/react/lineTool-WNI5EMZ5.js +14 -0
  135. package/dist/react/lineTool-WNI5EMZ5.js.map +7 -0
  136. package/dist/react/lixCode-OJMVUXXI.ttf +0 -0
  137. package/dist/react/lixDefault-JEAPAUJL.ttf +0 -0
  138. package/dist/react/lixFancy-BPXYM5CQ.ttf +0 -0
  139. package/dist/react/lixFont-CPKEUDVM.woff2 +0 -0
  140. package/dist/react/rectangleTool-U7DZ6ZTA.js +14 -0
  141. package/dist/react/rectangleTool-U7DZ6ZTA.js.map +7 -0
  142. package/dist/react/styles.css +6627 -0
  143. package/dist/react/textTool-M7S6F3VC.js +21 -0
  144. package/dist/react/textTool-M7S6F3VC.js.map +7 -0
  145. package/package.json +39 -5
  146. package/src/EngineShortcuts.js +83 -27
  147. package/src/core/AIRenderer.js +30 -18
  148. package/src/core/GraphEngine.js +64 -41
  149. package/src/core/MermaidFlowchartRenderer.js +153 -88
  150. package/src/core/MermaidSequenceRenderer.js +168 -93
  151. package/src/core/SceneSerializer.js +86 -2
  152. package/src/core/Selection.js +119 -19
  153. package/src/core/UndoRedo.js +82 -15
  154. package/src/core/ZoomPan.js +15 -5
  155. package/src/index.js +14 -1
  156. package/src/react/LixSketchCanvas.jsx +347 -0
  157. package/src/react/components/AppMenu.jsx +482 -0
  158. package/src/react/components/Footer.jsx +85 -0
  159. package/src/react/components/Toolbar.jsx +140 -0
  160. package/src/react/components/canvas/CanvasLoadingOverlay.jsx +76 -0
  161. package/src/react/components/canvas/ContextMenu.jsx +466 -0
  162. package/src/react/components/canvas/FindBar.jsx +177 -0
  163. package/src/react/components/canvas/ImageSourcePicker.jsx +133 -0
  164. package/src/react/components/canvas/MultiSelectActions.jsx +120 -0
  165. package/src/react/components/canvas/SVGCanvas.jsx +145 -0
  166. package/src/react/components/canvas/SaveStatusIndicator.jsx +29 -0
  167. package/src/react/components/modals/CanvasPropertiesModal.jsx +358 -0
  168. package/src/react/components/modals/CommandPalette.jsx +307 -0
  169. package/src/react/components/modals/ExportImageModal.jsx +287 -0
  170. package/src/react/components/modals/GraphModal.jsx +174 -0
  171. package/src/react/components/modals/HelpModal.jsx +208 -0
  172. package/src/react/components/modals/LixScriptModal.jsx +130 -0
  173. package/src/react/components/modals/ShortcutsModal.jsx +125 -0
  174. package/src/react/components/sidebars/ArrowSidebar.jsx +173 -0
  175. package/src/react/components/sidebars/CircleSidebar.jsx +134 -0
  176. package/src/react/components/sidebars/FrameSidebar.jsx +263 -0
  177. package/src/react/components/sidebars/IconSidebar.jsx +279 -0
  178. package/src/react/components/sidebars/ImageSidebar.jsx +69 -0
  179. package/src/react/components/sidebars/LineSidebar.jsx +109 -0
  180. package/src/react/components/sidebars/PaintbrushSidebar.jsx +119 -0
  181. package/src/react/components/sidebars/RectangleSidebar.jsx +165 -0
  182. package/src/react/components/sidebars/ShapeSidebar.jsx +130 -0
  183. package/src/react/components/sidebars/TextSidebar.jsx +174 -0
  184. package/src/react/hooks/inertStores.js +58 -0
  185. package/src/react/hooks/useSketchEngine.js +76 -0
  186. package/src/react/hooks/useTranslation.js +92 -0
  187. package/src/react/index.js +41 -0
  188. package/src/react/store/useSketchStore.js +234 -0
  189. package/src/react/store/useUIStore.js +196 -0
  190. package/src/react/styles/arrowSidebar.css +263 -0
  191. package/src/react/styles/canvasStroke.css +47 -0
  192. package/src/react/styles/canvasTools.css +769 -0
  193. package/src/react/styles/circleSidebar.css +206 -0
  194. package/src/react/styles/fonts/fonts.css +29 -0
  195. package/src/react/styles/fonts/lixCode.ttf +0 -0
  196. package/src/react/styles/fonts/lixDefault.ttf +0 -0
  197. package/src/react/styles/fonts/lixDocs.ttf +0 -0
  198. package/src/react/styles/fonts/lixFancy.ttf +0 -0
  199. package/src/react/styles/fonts/lixFont.woff2 +0 -0
  200. package/src/react/styles/lineSidebar.css +207 -0
  201. package/src/react/styles/paintbrushSidebar.css +247 -0
  202. package/src/react/styles/squareSidebar.css +206 -0
  203. package/src/react/styles/writeText.css +149 -0
  204. package/src/react/styles.css +175 -0
  205. package/src/react/toolsEnum.js +20 -0
  206. package/src/react/utils/toast.js +18 -0
  207. package/src/shapes/Frame.js +7 -1
  208. package/src/shapes/Line.js +11 -5
  209. package/src/tools/arrowTool.js +30 -4
  210. package/src/tools/circleTool.js +33 -9
  211. package/src/tools/codeTool.js +5 -3
  212. package/src/tools/frameTool.js +47 -7
  213. package/src/tools/freehandTool.js +12 -4
  214. package/src/tools/iconTool.js +7 -1
  215. package/src/tools/imageTool.js +7 -1
  216. package/src/tools/lineTool.js +27 -3
  217. package/src/tools/rectangleTool.js +45 -8
  218. package/src/tools/textTool.js +23 -6
@@ -0,0 +1,196 @@
1
+ import { create } from 'zustand'
2
+
3
+ /**
4
+ * Swap black↔white colors on all shapes when theme changes.
5
+ * prevTheme / nextTheme are resolved ('dark' | 'light').
6
+ */
7
+ function invertShapeColors(prevResolved, nextResolved) {
8
+ if (prevResolved === nextResolved) return
9
+ const shapes = window.shapes
10
+ if (!shapes || shapes.length === 0) return
11
+
12
+ // Going light → dark: #000 → #fff. Going dark → light: #fff → #000.
13
+ const from = nextResolved === 'light' ? '#ffffff' : '#000000'
14
+ const to = nextResolved === 'light' ? '#000000' : '#ffffff'
15
+
16
+ const normalize = (c) => {
17
+ if (!c || c === 'transparent' || c === 'none') return c
18
+ const lower = c.toLowerCase().trim()
19
+ if (lower === '#fff' || lower === '#ffffff' || lower === 'white') return '#ffffff'
20
+ if (lower === '#000' || lower === '#000000' || lower === 'black') return '#000000'
21
+ return lower
22
+ }
23
+
24
+ for (const shape of shapes) {
25
+ let changed = false
26
+ if (shape.options) {
27
+ if (normalize(shape.options.stroke) === from) {
28
+ shape.options.stroke = to
29
+ changed = true
30
+ }
31
+ if (normalize(shape.options.fill) === from) {
32
+ shape.options.fill = to
33
+ changed = true
34
+ }
35
+ }
36
+ // Text shapes store color directly
37
+ if (shape.color !== undefined && normalize(shape.color) === from) {
38
+ shape.color = to
39
+ changed = true
40
+ }
41
+ if (shape.strokeColor !== undefined && normalize(shape.strokeColor) === from) {
42
+ shape.strokeColor = to
43
+ changed = true
44
+ }
45
+ if (changed && typeof shape.draw === 'function') {
46
+ shape.draw()
47
+ }
48
+ }
49
+ }
50
+
51
+ function applyTheme(theme) {
52
+ // Issue #38 bug #1: scope theme to body classes so light mode only
53
+ // affects the canvas, not the landing/blog pages. Token values live
54
+ // in `body.canvas-mode` (light default) and `body.canvas-mode.theme-
55
+ // dark` (toggle) rules in src/app/globals.css.
56
+ const body = document.body
57
+ if (!body) return
58
+ const resolved = theme === 'system'
59
+ ? (window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light')
60
+ : theme
61
+ body.classList.remove('theme-dark', 'theme-light')
62
+ if (resolved === 'dark') body.classList.add('theme-dark')
63
+
64
+ const svgEl = window.svg
65
+ if (svgEl) svgEl.style.background = resolved === 'light' ? '#f4f3ee' : ''
66
+ }
67
+
68
+ const useUIStore = create((set, get) => ({
69
+ // --- Modals ---
70
+ shortcutsModalOpen: false,
71
+ saveModalOpen: false,
72
+ aiModalOpen: false,
73
+ graphModalOpen: false,
74
+ commandPaletteOpen: false,
75
+ helpModalOpen: false,
76
+ exportImageModalOpen: false,
77
+ findBarOpen: false,
78
+ canvasPropertiesOpen: false,
79
+ imageGenerateModalOpen: false,
80
+
81
+ toggleShortcutsModal: () =>
82
+ set((s) => ({ shortcutsModalOpen: !s.shortcutsModalOpen })),
83
+ toggleSaveModal: () =>
84
+ set((s) => ({ saveModalOpen: !s.saveModalOpen })),
85
+ toggleAIModal: () =>
86
+ set((s) => ({ aiModalOpen: !s.aiModalOpen })),
87
+ toggleGraphModal: () =>
88
+ set((s) => ({ graphModalOpen: !s.graphModalOpen })),
89
+ toggleCommandPalette: () =>
90
+ set((s) => ({ commandPaletteOpen: !s.commandPaletteOpen })),
91
+ toggleHelpModal: () =>
92
+ set((s) => ({ helpModalOpen: !s.helpModalOpen })),
93
+ toggleExportImageModal: () =>
94
+ set((s) => ({ exportImageModalOpen: !s.exportImageModalOpen })),
95
+ toggleFindBar: () =>
96
+ set((s) => ({ findBarOpen: !s.findBarOpen })),
97
+ closeFindBar: () =>
98
+ set({ findBarOpen: false }),
99
+ toggleCanvasProperties: () =>
100
+ set((s) => ({ canvasPropertiesOpen: !s.canvasPropertiesOpen })),
101
+ toggleImageGenerateModal: () =>
102
+ set((s) => ({ imageGenerateModalOpen: !s.imageGenerateModalOpen })),
103
+ closeImageGenerateModal: () =>
104
+ set({ imageGenerateModalOpen: false }),
105
+ closeAllModals: () =>
106
+ set({ shortcutsModalOpen: false, saveModalOpen: false, aiModalOpen: false, graphModalOpen: false, commandPaletteOpen: false, helpModalOpen: false, exportImageModalOpen: false, findBarOpen: false, canvasPropertiesOpen: false, imageGenerateModalOpen: false }),
107
+
108
+ // --- Menu ---
109
+ menuOpen: false,
110
+ toggleMenu: () => set((s) => ({ menuOpen: !s.menuOpen })),
111
+ closeMenu: () => set({ menuOpen: false }),
112
+
113
+ // --- Workspace ---
114
+ workspaceName: '',
115
+ setWorkspaceName: (name) => {
116
+ if (typeof window !== 'undefined') {
117
+ localStorage.setItem('lixsketch-workspace-name', name)
118
+ }
119
+ set({ workspaceName: name })
120
+ },
121
+
122
+ // --- Save Status ---
123
+ // 'idle' | 'local' | 'cloud' | 'failed'
124
+ saveStatus: 'idle',
125
+ setSaveStatus: (status) => set({ saveStatus: status }),
126
+
127
+ // --- Session / Encryption ---
128
+ // Key is persisted in localStorage keyed by session ID so it survives page refreshes.
129
+ // This ensures re-saving a workspace uses the same key, keeping old share links valid.
130
+ sessionEncryptionKey: null,
131
+ setSessionEncryptionKey: (key, sessionId) => {
132
+ if (typeof window !== 'undefined' && sessionId) {
133
+ localStorage.setItem(`lixsketch-enc-key-${sessionId}`, key)
134
+ }
135
+ set({ sessionEncryptionKey: key })
136
+ },
137
+ loadEncryptionKeyForSession: (sessionId) => {
138
+ if (typeof window !== 'undefined' && sessionId) {
139
+ const stored = localStorage.getItem(`lixsketch-enc-key-${sessionId}`)
140
+ if (stored) {
141
+ set({ sessionEncryptionKey: stored })
142
+ return stored
143
+ }
144
+ }
145
+ return null
146
+ },
147
+ clearEncryptionKeyForSession: (sessionId) => {
148
+ if (typeof window !== 'undefined' && sessionId) {
149
+ localStorage.removeItem(`lixsketch-enc-key-${sessionId}`)
150
+ }
151
+ set({ sessionEncryptionKey: null })
152
+ },
153
+
154
+ // --- Canvas Loading ---
155
+ canvasLoading: false,
156
+ canvasLoadingMessage: 'Loading canvas...',
157
+ setCanvasLoading: (loading, message) => set({ canvasLoading: loading, canvasLoadingMessage: message || 'Loading canvas...' }),
158
+
159
+ // --- Theme ---
160
+ // Issue #38 bug #1: light by default. Dark stays available via toggle.
161
+ theme: 'light',
162
+ setTheme: (newTheme) => {
163
+ const prev = get().theme
164
+ const resolve = (t) => t === 'system'
165
+ ? (window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light')
166
+ : t
167
+ invertShapeColors(resolve(prev), resolve(newTheme))
168
+ applyTheme(newTheme)
169
+ set({ theme: newTheme })
170
+ },
171
+
172
+ // --- Language / i18n ---
173
+ language: 'en',
174
+ setLanguage: (lang) => {
175
+ set({ language: lang })
176
+ },
177
+ persistUIPrefs: (prefs) => {
178
+ if (typeof window !== 'undefined') {
179
+ const existing = localStorage.getItem('lix_ui_prefs')
180
+ let parsed = {}
181
+ try {
182
+ if (existing) parsed = JSON.parse(existing)
183
+ } catch (e) {}
184
+
185
+ const updated = { ...parsed, ...prefs }
186
+ localStorage.setItem('lix_ui_prefs', JSON.stringify(updated))
187
+
188
+ if (prefs.language) {
189
+ set({ language: prefs.language })
190
+ window.dispatchEvent(new CustomEvent('lix-language-changed', { detail: { language: prefs.language } }))
191
+ }
192
+ }
193
+ }
194
+ }))
195
+
196
+ export default useUIStore
@@ -0,0 +1,263 @@
1
+ .arrowSideBar {
2
+ position: fixed;
3
+ bottom: 20px;
4
+ left: 50%;
5
+ transform: translateX(-50%);
6
+ width: auto;
7
+ border-radius: 15px;
8
+ height: auto;
9
+ background-color: #232329;
10
+ overflow: visible;
11
+ padding: 5px 10px;
12
+ transition: 0.5s;
13
+ z-index: 100;
14
+ display: flex;
15
+ flex-direction: row;
16
+ align-items: center;
17
+ filter: blur(0px);
18
+ opacity: 1;
19
+ }
20
+
21
+ .arrowSideBar.hidden {
22
+ opacity: 0;
23
+ pointer-events: none;
24
+ filter: blur(10px);
25
+ transform: translateX(-50%) translateY(20px);
26
+ transition: 0.5s;
27
+ z-index: -1;
28
+ }
29
+
30
+ /* Combined Labels */
31
+ .arrowColorLabel,
32
+ .arrowThicknessLabel,
33
+ .arrowStyleLabel,
34
+ .arrowTypeLabel,
35
+ .arrowHeadLabel,
36
+ .arrowCurveLabel {
37
+ display: none;
38
+ }
39
+
40
+ /* Combined containers */
41
+ .arrowColorsarrow,
42
+ .arrowThickness,
43
+ .arrowStyle,
44
+ .arrowType,
45
+ .arrowHead,
46
+ .arrowCurve {
47
+ position: static;
48
+ display: flex;
49
+ justify-content: flex-start;
50
+ flex-wrap: nowrap;
51
+ height: 40px;
52
+ gap: 5px;
53
+ align-items: center;
54
+ padding: 0 8px;
55
+ box-sizing: border-box;
56
+ border-right: 1px solid rgba(255,255,255,0.15);
57
+ }
58
+
59
+ .arrowCurve {
60
+ border-right: none;
61
+ }
62
+
63
+
64
+ /* Combined styles for color, background and fill spans */
65
+ .arrowColorsarrow span {
66
+ position: relative;
67
+ width: 30px;
68
+ height: 30px;
69
+ border-radius: 10px;
70
+ margin: 0 2px;
71
+ cursor: pointer;
72
+ box-sizing: border-box;
73
+ transition: 0.25s;
74
+ flex-shrink: 0;
75
+ }
76
+
77
+ /* Curve presets */
78
+ .arrowCurve span {
79
+ width: 35px;
80
+ height: 35px;
81
+ border-radius: 10px;
82
+ cursor: pointer;
83
+ color: #fff;
84
+ background: #31303B;
85
+ align-items: center;
86
+ justify-content: center;
87
+ display: flex;
88
+ transition: 0.25s;
89
+ border: 2px solid transparent;
90
+ flex-shrink: 0;
91
+ }
92
+ .arrowCurve span.selected {
93
+ background: #444480;
94
+ border: 2px solid #3c09d6;
95
+ transition: 0.25s;
96
+ transform: scale(1.1);
97
+ }
98
+ .arrowCurve span svg {
99
+ width: 28px;
100
+ height: 28px;
101
+ stroke: #fff;
102
+ }
103
+
104
+ /* Combined selected styles for color background and fill spans */
105
+ .arrowColorsarrow span.selected
106
+ {
107
+ border: 2px solid #3c09d6;
108
+ transform: scale(1.3); /* Using transform instead of scale */
109
+ transition: 0.25s;
110
+ }
111
+
112
+ /* Color-specific styles */
113
+ .arrowColorsarrow span:nth-child(1) { background-color: #fff; }
114
+ .arrowColorsarrow span:nth-child(2) { background: #FF8383; }
115
+ .arrowColorsarrow span:nth-child(3) { background-color: #3A994C; }
116
+ .arrowColorsarrow span:nth-child(4) { background-color: #56A2E8; }
117
+ .arrowColorsarrow span:nth-child(5) { background: #FFD700; }
118
+
119
+ /* Background-specific styles */
120
+ .arrowBackground span:nth-child(1) { background-color: #fff; }
121
+ .arrowBackground span:nth-child(2) { background-color: #5B2D2D; }
122
+ .arrowBackground span:nth-child(3) { background-color: #043B0C; }
123
+ .arrowBackground span:nth-child(4) { background-color: #154163; }
124
+ .arrowBackground span:nth-child(5) { background-color: #362600; }
125
+
126
+
127
+ /* Thickness styles */
128
+ .arrowThickness span {
129
+ width: 40px;
130
+ height: 40px;
131
+ position: relative;
132
+ left: 0;
133
+ border-radius: 10px;
134
+ margin: 0 5px;
135
+ cursor: pointer;
136
+ color: #fff;
137
+ background: #31303B;
138
+ align-items: center;
139
+ justify-content: center;
140
+ display: flex;
141
+ font-size: 30px;
142
+ transition: 0.25s;
143
+ flex-shrink: 0; /* Prevent shrinking */
144
+ }
145
+
146
+ .arrowThickness span.selected {
147
+ background: #444480;
148
+ transition: 0.25s;
149
+ }
150
+
151
+ .arrowThickness span:nth-child(1) { font-weight: 100; }
152
+ .arrowThickness span:nth-child(2) { font-weight: 500; }
153
+ .arrowThickness span:nth-child(3) { font-weight: 700; }
154
+
155
+ /* Fill styles */
156
+
157
+
158
+ .arrowStyle
159
+ {
160
+ gap: 20px;
161
+ }
162
+ /* Style styles */
163
+ .arrowStyle span {
164
+ width: 35px;
165
+ height: 35px;
166
+ left: 10%;
167
+ border-radius: 10px;
168
+ margin: 0; /* Remove left-right margins */
169
+ cursor: pointer;
170
+ color: #fff;
171
+ background: #31303B;
172
+ align-items: center;
173
+ justify-content: center;
174
+ display: flex;
175
+ transition: 0.25s;
176
+ border: 2px solid transparent;
177
+ flex-shrink: 0; /* Prevent shrinking */
178
+ }
179
+
180
+ .arrowStyle span.selected {
181
+ background: #444480;
182
+ border: 2px solid #3c09d6;
183
+ transition: 0.25s;
184
+ transform: scale(1.1); /* Using transform instead of scale */
185
+ }
186
+
187
+ .arrowStyle span svg {
188
+ width: 30px;
189
+ height: 30px;
190
+ stroke: #fff;
191
+ transition: 0.25s;
192
+ }
193
+
194
+ .arrowStyle span.selected svg {
195
+ stroke: #FFD700;
196
+ }
197
+
198
+ .arrowType
199
+ {
200
+ gap: 20px;
201
+ }
202
+ .arrowType span
203
+ {
204
+ width: 35px;
205
+ height: 35px;
206
+ left: 10%;
207
+ border-radius: 10px;
208
+ margin: 0; /* Remove left-right margins */
209
+ cursor: pointer;
210
+ color: #fff;
211
+ background: #31303B;
212
+ align-items: center;
213
+ justify-content: center;
214
+ display: flex;
215
+ transition: 0.25s;
216
+ border: 2px solid transparent;
217
+ flex-shrink: 0; /* Prevent shrinking */
218
+ }
219
+
220
+ .arrowType span.selected
221
+ {
222
+ background: #444480;
223
+ border: 2px solid #3c09d6;
224
+ transition: 0.25s;
225
+ transform: scale(1.1);
226
+ }
227
+ .arrowType span svg {
228
+ width: 30px;
229
+ height: 30px;
230
+ stroke: #fff;
231
+ transition: 0.25s;
232
+ }
233
+
234
+ .arrowHead
235
+ {
236
+ gap: 10px;
237
+ }
238
+
239
+ .arrowHead span.selected
240
+ {
241
+ background: #444480;
242
+ border: 2px solid #3c09d6;
243
+ transition: 0.25s;
244
+ transform: scale(1.1);
245
+ }
246
+
247
+ .arrowHead span
248
+ {
249
+ width: 35px;
250
+ height: 35px;
251
+ left: 10%;
252
+ border-radius: 10px;
253
+ margin: 0; /* Remove left-right margins */
254
+ cursor: pointer;
255
+ color: #fff;
256
+ background: #31303B;
257
+ align-items: center;
258
+ justify-content: center;
259
+ display: flex;
260
+ transition: 0.25s;
261
+ border: 2px solid transparent;
262
+ flex-shrink: 0; /* Prevent shrinking */
263
+ }
@@ -0,0 +1,47 @@
1
+ * {
2
+ margin: 0;
3
+ padding: 0;
4
+ }
5
+ html, body {
6
+ width: 100%;
7
+ height: 100%;
8
+ overflow: hidden;
9
+ background-color: #f0f0f0;
10
+ }
11
+
12
+ .container
13
+ {
14
+ display: flex;
15
+ justify-content: center;
16
+ align-items: center;
17
+ width: 100%;
18
+ height: 100%;
19
+ background: #121212;
20
+ position: relative;
21
+ }
22
+
23
+
24
+ svg {
25
+ width: 100vw;
26
+ height: 100vh;
27
+ touch-action: none;
28
+ }
29
+
30
+ path {
31
+ stroke-linecap: round;
32
+ stroke-linejoin: round;
33
+ }
34
+ #freehand-canvas
35
+ {
36
+ overflow: hidden;
37
+ max-height: 100%;
38
+ max-width: 100%;
39
+ }
40
+ #freehand-canvas g,
41
+ #freehand-canvas path {
42
+ pointer-events: all;
43
+ z-index: 1000;
44
+
45
+ }
46
+
47
+