sagadeck 1.2.0

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 (233) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +305 -0
  3. package/SKILL.md +148 -0
  4. package/bin/sagadeck.js +511 -0
  5. package/docs/ANDAMENTO.md +1255 -0
  6. package/docs/EXPERIENCIAS.md +39 -0
  7. package/docs/PLANO-EXPERIENCIAS.md +39 -0
  8. package/docs/PLANO-TESTE-AULAS-TECNICAS.md +44 -0
  9. package/docs/PLANO-TESTE-DESINFORMACAO.md +38 -0
  10. package/docs/REFERENCIA.md +1131 -0
  11. package/package.json +59 -0
  12. package/src/adaptive-layouts.js +18 -0
  13. package/src/ai/art-direction.js +8 -0
  14. package/src/ai/commands.js +130 -0
  15. package/src/ai/context.js +245 -0
  16. package/src/ai/deck-ai.js +1135 -0
  17. package/src/ai/directions.js +74 -0
  18. package/src/ai/document-materials.js +49 -0
  19. package/src/ai/document-visuals.js +215 -0
  20. package/src/ai/evaluation.js +31 -0
  21. package/src/ai/ground.js +55 -0
  22. package/src/ai/llm.js +292 -0
  23. package/src/ai/quality.js +51 -0
  24. package/src/ai/relay.js +45 -0
  25. package/src/ai/staged-generation.js +24 -0
  26. package/src/ai/transform.js +858 -0
  27. package/src/ai/usage.js +17 -0
  28. package/src/ai/variety.js +80 -0
  29. package/src/ai/video-frames.js +24 -0
  30. package/src/ai/video-generation.js +126 -0
  31. package/src/ai/web-operation.js +31 -0
  32. package/src/algo-catalog.js +153 -0
  33. package/src/algo-trace.js +139 -0
  34. package/src/api-client.js +514 -0
  35. package/src/api-collections.js +14 -0
  36. package/src/api-demo.js +222 -0
  37. package/src/aspect.js +40 -0
  38. package/src/build.js +323 -0
  39. package/src/carousel.js +56 -0
  40. package/src/chrome.js +65 -0
  41. package/src/code-highlight.js +68 -0
  42. package/src/code-lab-browser.js +22 -0
  43. package/src/code-lab.js +3 -0
  44. package/src/code-language.js +52 -0
  45. package/src/csv.js +74 -0
  46. package/src/decision-lab.js +20 -0
  47. package/src/deck-file.js +119 -0
  48. package/src/diagram/napkin-examples.js +13 -0
  49. package/src/diagram/napkin.js +539 -0
  50. package/src/docx.js +128 -0
  51. package/src/dynamics/git-sim.js +200 -0
  52. package/src/dynamics/layouts.js +112 -0
  53. package/src/elements.js +554 -0
  54. package/src/experiences.js +124 -0
  55. package/src/exploration.js +31 -0
  56. package/src/export/browser.js +53 -0
  57. package/src/export/estudo.js +67 -0
  58. package/src/export/pptx.js +475 -0
  59. package/src/export/roteiro.js +40 -0
  60. package/src/export/shots.js +182 -0
  61. package/src/figures/charts.js +383 -0
  62. package/src/figures/diagrams.js +117 -0
  63. package/src/figures/icons.js +166 -0
  64. package/src/figures/material-pictos.js +20 -0
  65. package/src/figures/pictos.js +255 -0
  66. package/src/figures/points.js +106 -0
  67. package/src/figures/qr.js +29 -0
  68. package/src/figures/ufmap.js +48 -0
  69. package/src/fiscal/autofix.js +377 -0
  70. package/src/fiscal/normalize.js +115 -0
  71. package/src/graph-lab.js +24 -0
  72. package/src/hologram.js +30 -0
  73. package/src/identity.js +86 -0
  74. package/src/import/crop.js +59 -0
  75. package/src/import/index.js +132 -0
  76. package/src/import/legacy-word.js +42 -0
  77. package/src/import/merge.js +45 -0
  78. package/src/import/office.js +123 -0
  79. package/src/import/omml.js +69 -0
  80. package/src/import/pdf-render.js +56 -0
  81. package/src/import/pptx.js +701 -0
  82. package/src/import/xml.js +42 -0
  83. package/src/infographic.js +401 -0
  84. package/src/layouts.js +723 -0
  85. package/src/lessons.js +171 -0
  86. package/src/library.js +399 -0
  87. package/src/markup.js +116 -0
  88. package/src/master.js +214 -0
  89. package/src/mcp/server.js +371 -0
  90. package/src/meeting.js +42 -0
  91. package/src/motion.js +56 -0
  92. package/src/package.js +116 -0
  93. package/src/playground.js +19 -0
  94. package/src/portal-scene.js +20 -0
  95. package/src/preferences.js +61 -0
  96. package/src/protect.js +51 -0
  97. package/src/purpose.js +24 -0
  98. package/src/pytrace.js +1092 -0
  99. package/src/research/duckduckgo.js +73 -0
  100. package/src/research/research.js +202 -0
  101. package/src/research/svg-image.js +17 -0
  102. package/src/research/visuals.js +52 -0
  103. package/src/runtime/api-collection-ui.js +5 -0
  104. package/src/runtime/api-collections.js +28 -0
  105. package/src/runtime/api-core.js +530 -0
  106. package/src/runtime/api-ui.js +966 -0
  107. package/src/runtime/base.css +1774 -0
  108. package/src/runtime/calc.js +139 -0
  109. package/src/runtime/code-lab.js +371 -0
  110. package/src/runtime/decision-lab.js +49 -0
  111. package/src/runtime/diagram.js +341 -0
  112. package/src/runtime/fit.js +268 -0
  113. package/src/runtime/fonts/caveat.css +2 -0
  114. package/src/runtime/fonts/comic-neue.css +3 -0
  115. package/src/runtime/fonts/fredoka.css +2 -0
  116. package/src/runtime/fonts/index.json +10 -0
  117. package/src/runtime/fonts/inter.css +2 -0
  118. package/src/runtime/fonts/patrick-hand.css +2 -0
  119. package/src/runtime/fonts/plus-jakarta-sans.css +2 -0
  120. package/src/runtime/fonts/press-start-2p.css +2 -0
  121. package/src/runtime/fonts/vt323.css +2 -0
  122. package/src/runtime/formula.js +148 -0
  123. package/src/runtime/graph-lab.js +72 -0
  124. package/src/runtime/meeting.css +7 -0
  125. package/src/runtime/meeting.js +10 -0
  126. package/src/runtime/motion.js +15 -0
  127. package/src/runtime/playground.js +11 -0
  128. package/src/runtime/points.js +19 -0
  129. package/src/runtime/portal-scene.css +6 -0
  130. package/src/runtime/portal-scene.js +22 -0
  131. package/src/runtime/runtime.js +827 -0
  132. package/src/runtime/science.js +89 -0
  133. package/src/runtime/skins/aluminio.css +31 -0
  134. package/src/runtime/skins/arcade.css +25 -0
  135. package/src/runtime/skins/aurora.css +17 -0
  136. package/src/runtime/skins/bauhaus.css +19 -0
  137. package/src/runtime/skins/editorial.css +19 -0
  138. package/src/runtime/skins/jornal.css +17 -0
  139. package/src/runtime/skins/manual-noite.css +14 -0
  140. package/src/runtime/skins/manual.css +14 -0
  141. package/src/runtime/skins/noite.css +21 -0
  142. package/src/runtime/skins/oceano.css +17 -0
  143. package/src/runtime/skins/pop.css +23 -0
  144. package/src/runtime/skins/prata.css +18 -0
  145. package/src/runtime/skins/prisma.css +28 -0
  146. package/src/runtime/skins/rabisco.css +18 -0
  147. package/src/runtime/skins/relevo.css +33 -0
  148. package/src/runtime/skins/sinal.css +16 -0
  149. package/src/runtime/skins/terminal.css +23 -0
  150. package/src/runtime/vendor/KATEX-LICENSE.txt +21 -0
  151. package/src/runtime/vendor/MERMAID-LICENSE.txt +21 -0
  152. package/src/runtime/vendor/PLOTLY-LICENSE.txt +21 -0
  153. package/src/runtime/vendor/katex.css +1 -0
  154. package/src/runtime/vendor/mermaid.min.js +3636 -0
  155. package/src/runtime/vendor/plotly.min.js +3620 -0
  156. package/src/runtime/video-player.js +35 -0
  157. package/src/science.js +162 -0
  158. package/src/studio/ai-response.js +36 -0
  159. package/src/studio/api-routes.js +152 -0
  160. package/src/studio/assets/contexto/leia-me.md +12 -0
  161. package/src/studio/assets/contexto/vendas.csv +7 -0
  162. package/src/studio/assets/imagens/colecao-arquitetura.png +0 -0
  163. package/src/studio/assets/imagens/colecao-cor.png +0 -0
  164. package/src/studio/assets/imagens/colecao-equipe.png +0 -0
  165. package/src/studio/assets/imagens/lavanda-cover.jpg +0 -0
  166. package/src/studio/code-routes.js +32 -0
  167. package/src/studio/command-approval.js +48 -0
  168. package/src/studio/demo-decks.js +98 -0
  169. package/src/studio/direction-routes.js +29 -0
  170. package/src/studio/errors.js +65 -0
  171. package/src/studio/exploration-demo.js +17 -0
  172. package/src/studio/exporting.js +105 -0
  173. package/src/studio/generation-report.js +10 -0
  174. package/src/studio/instance.js +48 -0
  175. package/src/studio/layout-samples.js +152 -0
  176. package/src/studio/project.js +371 -0
  177. package/src/studio/public/api-collections.js +28 -0
  178. package/src/studio/public/app.js +5265 -0
  179. package/src/studio/public/art-preview.js +10 -0
  180. package/src/studio/public/calc-fields.js +11 -0
  181. package/src/studio/public/chat-progress.js +47 -0
  182. package/src/studio/public/developer-fields.js +22 -0
  183. package/src/studio/public/explorer.js +443 -0
  184. package/src/studio/public/history.js +58 -0
  185. package/src/studio/public/index.html +867 -0
  186. package/src/studio/public/inspector.js +270 -0
  187. package/src/studio/public/lab-fields.js +5 -0
  188. package/src/studio/public/library.css +275 -0
  189. package/src/studio/public/library.html +55 -0
  190. package/src/studio/public/library.js +471 -0
  191. package/src/studio/public/merge-decks.js +155 -0
  192. package/src/studio/public/review-ui.js +100 -0
  193. package/src/studio/public/screenshot-editor.js +140 -0
  194. package/src/studio/public/share-ui.js +72 -0
  195. package/src/studio/public/slide-clipboard.js +23 -0
  196. package/src/studio/public/slide-form.js +1263 -0
  197. package/src/studio/public/studio-awareness.js +154 -0
  198. package/src/studio/public/studio-next.css +303 -0
  199. package/src/studio/public/style.css +1262 -0
  200. package/src/studio/public/ui-icons.js +2 -0
  201. package/src/studio/public/viewers.js +372 -0
  202. package/src/studio/public/visual-editor.js +326 -0
  203. package/src/studio/public/workspace.js +18 -0
  204. package/src/studio/public-files.js +1 -0
  205. package/src/studio/request-helpers.js +41 -0
  206. package/src/studio/server.js +1583 -0
  207. package/src/studio/share-routes.js +146 -0
  208. package/src/studio/slide-copy-routes.js +26 -0
  209. package/src/studio/slide-copy.js +30 -0
  210. package/src/studio/snapshot.js +160 -0
  211. package/src/studio/style-routes.js +103 -0
  212. package/src/studio/template-collections.js +97 -0
  213. package/src/studio/versions.js +95 -0
  214. package/src/studio/video-download.js +29 -0
  215. package/src/studio/visual-keys.js +52 -0
  216. package/src/studio/workspaces.js +39 -0
  217. package/src/table.js +93 -0
  218. package/src/templates/scaffold.js +372 -0
  219. package/src/themes.js +604 -0
  220. package/src/trace-view.js +450 -0
  221. package/src/uid.js +19 -0
  222. package/src/video-player.js +40 -0
  223. package/src/visual-edits.js +99 -0
  224. package/src/ws.js +134 -0
  225. package/templates/cenario/Texto no cen/303/241rio.yaml" +171 -0
  226. package/templates/cenario/imagens/cidade.svg +30 -0
  227. package/templates/cenario/imagens/pessoa.svg +15 -0
  228. package/templates/cenario-e-ciencia.yaml +47 -0
  229. package/templates/ensaio-api.yaml +160 -0
  230. package/templates/exemplo-alegre.yaml +75 -0
  231. package/templates/exemplo-keynote.yaml +90 -0
  232. package/templates/exemplo-napkin.yaml +139 -0
  233. package/templates/exemplo.yaml +228 -0
@@ -0,0 +1,2 @@
1
+ // GERADO por scripts/vendor-ui-icons.mjs — não edite à mão. Ícones Lucide (ISC), https://lucide.dev
2
+ window.UI_ICONS = {"folder-tree":"<path d=\"M20 10a1 1 0 0 0 1-1V6a1 1 0 0 0-1-1h-2.5a1 1 0 0 1-.8-.4l-.9-1.2A1 1 0 0 0 15 3h-2a1 1 0 0 0-1 1v5a1 1 0 0 0 1 1Z\" /><path d=\"M20 21a1 1 0 0 0 1-1v-3a1 1 0 0 0-1-1h-2.9a1 1 0 0 1-.88-.55l-.42-.85a1 1 0 0 0-.92-.6H13a1 1 0 0 0-1 1v5a1 1 0 0 0 1 1Z\" /><path d=\"M3 5a2 2 0 0 0 2 2h3\" /><path d=\"M3 3v13a2 2 0 0 0 2 2h3\" />","file-spreadsheet":"<path d=\"M6 22a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h8a2.4 2.4 0 0 1 1.704.706l3.588 3.588A2.4 2.4 0 0 1 20 8v12a2 2 0 0 1-2 2z\" /><path d=\"M14 2v5a1 1 0 0 0 1 1h5\" /><path d=\"M8 13h2\" /><path d=\"M14 13h2\" /><path d=\"M8 17h2\" /><path d=\"M14 17h2\" />","file-image":"<path d=\"M6 22a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h8a2.4 2.4 0 0 1 1.704.706l3.588 3.588A2.4 2.4 0 0 1 20 8v12a2 2 0 0 1-2 2z\" /><path d=\"M14 2v5a1 1 0 0 0 1 1h5\" /><circle cx=\"10\" cy=\"12\" r=\"2\" /><path d=\"m20 17-1.296-1.296a2.41 2.41 0 0 0-3.408 0L9 22\" />","table":"<path d=\"M12 3v18\" /><rect width=\"18\" height=\"18\" x=\"3\" y=\"3\" rx=\"2\" /><path d=\"M3 9h18\" /><path d=\"M3 15h18\" />","refresh-cw":"<path d=\"M3 12a9 9 0 0 1 9-9 9.75 9.75 0 0 1 6.74 2.74L21 8\" /><path d=\"M21 3v5h-5\" /><path d=\"M21 12a9 9 0 0 1-9 9 9.75 9.75 0 0 1-6.74-2.74L3 16\" /><path d=\"M8 16H3v5\" />","file":"<path d=\"M6 22a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h8a2.4 2.4 0 0 1 1.704.706l3.588 3.588A2.4 2.4 0 0 1 20 8v12a2 2 0 0 1-2 2z\" /><path d=\"M14 2v5a1 1 0 0 0 1 1h5\" />","wand-sparkles":"<path d=\"m21.64 3.64-1.28-1.28a1.21 1.21 0 0 0-1.72 0L2.36 18.64a1.21 1.21 0 0 0 0 1.72l1.28 1.28a1.2 1.2 0 0 0 1.72 0L21.64 5.36a1.2 1.2 0 0 0 0-1.72\" /><path d=\"m14 7 3 3\" /><path d=\"M5 6v4\" /><path d=\"M19 14v4\" /><path d=\"M10 2v2\" /><path d=\"M7 8H3\" /><path d=\"M21 16h-4\" /><path d=\"M11 3H9\" />","chart-column":"<path d=\"M3 3v16a2 2 0 0 0 2 2h16\" /><path d=\"M18 17V9\" /><path d=\"M13 17V5\" /><path d=\"M8 17v-3\" />","layers":"<path d=\"M12.83 2.18a2 2 0 0 0-1.66 0L2.6 6.08a1 1 0 0 0 0 1.83l8.58 3.91a2 2 0 0 0 1.66 0l8.58-3.9a1 1 0 0 0 0-1.83z\" /><path d=\"M2 12a1 1 0 0 0 .58.91l8.6 3.91a2 2 0 0 0 1.65 0l8.58-3.9A1 1 0 0 0 22 12\" /><path d=\"M2 17a1 1 0 0 0 .58.91l8.6 3.91a2 2 0 0 0 1.65 0l8.58-3.9A1 1 0 0 0 22 17\" />","clapperboard":"<path d=\"m12.296 3.464 3.02 3.956\" /><path d=\"M20.2 6 3 11l-.9-2.4c-.3-1.1.3-2.2 1.3-2.5l13.5-4c1.1-.3 2.2.3 2.5 1.3z\" /><path d=\"M3 11h18v8a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z\" /><path d=\"m6.18 5.276 3.1 3.899\" />","crosshair":"<circle cx=\"12\" cy=\"12\" r=\"10\" /><line x1=\"22\" x2=\"18\" y1=\"12\" y2=\"12\" /><line x1=\"6\" x2=\"2\" y1=\"12\" y2=\"12\" /><line x1=\"12\" x2=\"12\" y1=\"6\" y2=\"2\" /><line x1=\"12\" x2=\"12\" y1=\"22\" y2=\"18\" />","terminal":"<path d=\"M12 19h8\" /><path d=\"m4 17 6-6-6-6\" />","image":"<rect width=\"18\" height=\"18\" x=\"3\" y=\"3\" rx=\"2\" ry=\"2\" /><circle cx=\"9\" cy=\"9\" r=\"2\" /><path d=\"m21 15-3.086-3.086a2 2 0 0 0-2.828 0L6 21\" />","circle-help":"<circle cx=\"12\" cy=\"12\" r=\"10\" /><path d=\"M9.09 9a3 3 0 0 1 5.83 1c0 2-3 3-3 3\" /><path d=\"M12 17h.01\" />","plus":"<path d=\"M5 12h14\" /><path d=\"M12 5v14\" />","copy":"<rect width=\"14\" height=\"14\" x=\"8\" y=\"8\" rx=\"2\" ry=\"2\" /><path d=\"M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2\" />","trash-2":"<path d=\"M10 11v6\" /><path d=\"M14 11v6\" /><path d=\"M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6\" /><path d=\"M3 6h18\" /><path d=\"M8 6V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2\" />","layout-template":"<rect width=\"18\" height=\"7\" x=\"3\" y=\"3\" rx=\"1\" /><rect width=\"9\" height=\"7\" x=\"3\" y=\"14\" rx=\"1\" /><rect width=\"5\" height=\"7\" x=\"16\" y=\"14\" rx=\"1\" />","palette":"<path d=\"M12 22a1 1 0 0 1 0-20 10 9 0 0 1 10 9 5 5 0 0 1-5 5h-2.25a1.75 1.75 0 0 0-1.4 2.8l.3.4a1.75 1.75 0 0 1-1.4 2.8z\" /><circle cx=\"13.5\" cy=\"6.5\" r=\".5\" fill=\"currentColor\" /><circle cx=\"17.5\" cy=\"10.5\" r=\".5\" fill=\"currentColor\" /><circle cx=\"6.5\" cy=\"12.5\" r=\".5\" fill=\"currentColor\" /><circle cx=\"8.5\" cy=\"7.5\" r=\".5\" fill=\"currentColor\" />","sun-moon":"<path d=\"M12 2v2\" /><path d=\"M14.837 16.385a6 6 0 1 1-7.223-7.222c.624-.147.97.66.715 1.248a4 4 0 0 0 5.26 5.259c.589-.255 1.396.09 1.248.715\" /><path d=\"M16 12a4 4 0 0 0-4-4\" /><path d=\"m19 5-1.256 1.256\" /><path d=\"M20 12h2\" />","grid-3x3":"<rect width=\"18\" height=\"18\" x=\"3\" y=\"3\" rx=\"2\" /><path d=\"M3 9h18\" /><path d=\"M3 15h18\" /><path d=\"M9 3v18\" /><path d=\"M15 3v18\" />","sparkles":"<path d=\"M11.017 2.814a1 1 0 0 1 1.966 0l1.051 5.558a2 2 0 0 0 1.594 1.594l5.558 1.051a1 1 0 0 1 0 1.966l-5.558 1.051a2 2 0 0 0-1.594 1.594l-1.051 5.558a1 1 0 0 1-1.966 0l-1.051-5.558a2 2 0 0 0-1.594-1.594l-5.558-1.051a1 1 0 0 1 0-1.966l5.558-1.051a2 2 0 0 0 1.594-1.594z\" /><path d=\"M20 2v4\" /><path d=\"M22 4h-4\" /><circle cx=\"4\" cy=\"20\" r=\"2\" />","shapes":"<path d=\"M8.3 10a.7.7 0 0 1-.626-1.079L11.4 3a.7.7 0 0 1 1.198-.043L16.3 8.9a.7.7 0 0 1-.572 1.1Z\" /><rect x=\"3\" y=\"14\" width=\"7\" height=\"7\" rx=\"1\" /><circle cx=\"17.5\" cy=\"17.5\" r=\"3.5\" />","workflow":"<rect width=\"8\" height=\"8\" x=\"3\" y=\"3\" rx=\"2\" /><path d=\"M7 11v4a2 2 0 0 0 2 2h4\" /><rect width=\"8\" height=\"8\" x=\"13\" y=\"13\" rx=\"2\" />","folder-open":"<path d=\"m6 14 1.5-2.9A2 2 0 0 1 9.24 10H20a2 2 0 0 1 1.94 2.5l-1.54 6a2 2 0 0 1-1.95 1.5H4a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h3.9a2 2 0 0 1 1.69.9l.81 1.2a2 2 0 0 0 1.67.9H18a2 2 0 0 1 2 2v2\" />","folder-input":"<path d=\"M2 9V5a2 2 0 0 1 2-2h3.9a2 2 0 0 1 1.69.9l.81 1.2a2 2 0 0 0 1.67.9H20a2 2 0 0 1 2 2v10a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2v-1\" /><path d=\"M2 13h10\" /><path d=\"m9 16 3-3-3-3\" />","save":"<path d=\"M15.2 3a2 2 0 0 1 1.4.6l3.8 3.8a2 2 0 0 1 .6 1.4V19a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2z\" /><path d=\"M17 21v-7a1 1 0 0 0-1-1H8a1 1 0 0 0-1 1v7\" /><path d=\"M7 3v4a1 1 0 0 0 1 1h7\" />","download":"<path d=\"M12 15V3\" /><path d=\"M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4\" /><path d=\"m7 10 5 5 5-5\" />","file-code":"<path d=\"M6 22a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h8a2.4 2.4 0 0 1 1.704.706l3.588 3.588A2.4 2.4 0 0 1 20 8v12a2 2 0 0 1-2 2z\" /><path d=\"M14 2v5a1 1 0 0 0 1 1h5\" /><path d=\"M10 12.5 8 15l2 2.5\" /><path d=\"m14 12.5 2 2.5-2 2.5\" />","file-text":"<path d=\"M6 22a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h8a2.4 2.4 0 0 1 1.704.706l3.588 3.588A2.4 2.4 0 0 1 20 8v12a2 2 0 0 1-2 2z\" /><path d=\"M14 2v5a1 1 0 0 0 1 1h5\" /><path d=\"M10 9H8\" /><path d=\"M16 13H8\" /><path d=\"M16 17H8\" />","external-link":"<path d=\"M15 3h6v6\" /><path d=\"M10 14 21 3\" /><path d=\"M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6\" />","play":"<path d=\"M5 5a2 2 0 0 1 3.008-1.728l11.997 6.998a2 2 0 0 1 .003 3.458l-12 7A2 2 0 0 1 5 19z\" />","chevron-down":"<path d=\"m6 9 6 6 6-6\" />","search":"<path d=\"m21 21-4.34-4.34\" /><circle cx=\"11\" cy=\"11\" r=\"8\" />","x":"<path d=\"M18 6 6 18\" /><path d=\"m6 6 12 12\" />","bot":"<path d=\"M12 8V4H8\" /><rect width=\"16\" height=\"12\" x=\"4\" y=\"8\" rx=\"2\" /><path d=\"M2 14h2\" /><path d=\"M20 14h2\" /><path d=\"M15 13v2\" /><path d=\"M9 13v2\" />","message-square-text":"<path d=\"M22 17a2 2 0 0 1-2 2H6.828a2 2 0 0 0-1.414.586l-2.202 2.202A.71.71 0 0 1 2 21.286V5a2 2 0 0 1 2-2h16a2 2 0 0 1 2 2z\" /><path d=\"M7 11h10\" /><path d=\"M7 15h6\" /><path d=\"M7 7h8\" />","panel-right":"<rect width=\"18\" height=\"18\" x=\"3\" y=\"3\" rx=\"2\" /><path d=\"M15 3v18\" />","sticky-note":"<path d=\"M21 9a2.4 2.4 0 0 0-.706-1.706l-3.588-3.588A2.4 2.4 0 0 0 15 3H5a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2z\" /><path d=\"M15 3v5a1 1 0 0 0 1 1h5\" />","code-xml":"<path d=\"m18 16 4-4-4-4\" /><path d=\"m6 8-4 4 4 4\" /><path d=\"m14.5 4-5 16\" />","scan-eye":"<path d=\"M3 7V5a2 2 0 0 1 2-2h2\" /><path d=\"M17 3h2a2 2 0 0 1 2 2v2\" /><path d=\"M21 17v2a2 2 0 0 1-2 2h-2\" /><path d=\"M7 21H5a2 2 0 0 1-2-2v-2\" /><circle cx=\"12\" cy=\"12\" r=\"1\" /><path d=\"M18.944 12.33a1 1 0 0 0 0-.66 7.5 7.5 0 0 0-13.888 0 1 1 0 0 0 0 .66 7.5 7.5 0 0 0 13.888 0\" />","flame":"<path d=\"M12 3q1 4 4 6.5t3 5.5a1 1 0 0 1-14 0 5 5 0 0 1 1-3 1 1 0 0 0 5 0c0-2-1.5-3-1.5-5q0-2 2.5-4\" />","layout-dashboard":"<rect width=\"7\" height=\"9\" x=\"3\" y=\"3\" rx=\"1\" /><rect width=\"7\" height=\"5\" x=\"14\" y=\"3\" rx=\"1\" /><rect width=\"7\" height=\"9\" x=\"14\" y=\"12\" rx=\"1\" /><rect width=\"7\" height=\"5\" x=\"3\" y=\"16\" rx=\"1\" />","activity":"<path d=\"M22 12h-2.48a2 2 0 0 0-1.93 1.46l-2.35 8.36a.25.25 0 0 1-.48 0L9.24 2.18a.25.25 0 0 0-.48 0l-2.35 8.36A2 2 0 0 1 4.49 12H2\" />","wand":"<path d=\"M15 4V2\" /><path d=\"M15 16v-2\" /><path d=\"M8 9h2\" /><path d=\"M20 9h2\" /><path d=\"M17.8 11.8 19 13\" /><path d=\"M15 9h.01\" /><path d=\"M17.8 6.2 19 5\" /><path d=\"m3 21 9-9\" /><path d=\"M12.2 6.2 11 5\" />","square-dashed":"<path d=\"M5 3a2 2 0 0 0-2 2\" /><path d=\"M19 3a2 2 0 0 1 2 2\" /><path d=\"M21 19a2 2 0 0 1-2 2\" /><path d=\"M5 21a2 2 0 0 1-2-2\" /><path d=\"M9 3h1\" /><path d=\"M9 21h1\" /><path d=\"M14 3h1\" /><path d=\"M14 21h1\" /><path d=\"M3 9v1\" /><path d=\"M21 9v1\" /><path d=\"M3 14v1\" /><path d=\"M21 14v1\" />","scan-line":"<path d=\"M3 7V5a2 2 0 0 1 2-2h2\" /><path d=\"M17 3h2a2 2 0 0 1 2 2v2\" /><path d=\"M21 17v2a2 2 0 0 1-2 2h-2\" /><path d=\"M7 21H5a2 2 0 0 1-2-2v-2\" /><path d=\"M7 12h10\" />","volume-2":"<path d=\"M11 4.702a.705.705 0 0 0-1.203-.498L6.413 7.587A1.4 1.4 0 0 1 5.416 8H3a1 1 0 0 0-1 1v6a1 1 0 0 0 1 1h2.416a1.4 1.4 0 0 1 .997.413l3.383 3.384A.705.705 0 0 0 11 19.298z\" /><path d=\"M16 9a5 5 0 0 1 0 6\" /><path d=\"M19.364 18.364a9 9 0 0 0 0-12.728\" />","volume-x":"<path d=\"M11 4.702a.7.7 0 0 0-1.203-.498L6.413 7.587A1.4 1.4 0 0 1 5.416 8H3a1 1 0 0 0-1 1v6a1 1 0 0 0 1 1h2.416a1.4 1.4 0 0 1 .997.413l3.383 3.384A.7.7 0 0 0 11 19.298z\" /><path d=\"m16.5 14.5 5-5\" /><path d=\"m16.5 9.5 5 5\" />","zoom-in":"<circle cx=\"11\" cy=\"11\" r=\"8\" /><line x1=\"21\" x2=\"16.65\" y1=\"21\" y2=\"16.65\" /><line x1=\"11\" x2=\"11\" y1=\"8\" y2=\"14\" /><line x1=\"8\" x2=\"14\" y1=\"11\" y2=\"11\" />","zoom-out":"<circle cx=\"11\" cy=\"11\" r=\"8\" /><line x1=\"21\" x2=\"16.65\" y1=\"21\" y2=\"16.65\" /><line x1=\"8\" x2=\"14\" y1=\"11\" y2=\"11\" />","maximize":"<path d=\"M8 3H5a2 2 0 0 0-2 2v3\" /><path d=\"M21 8V5a2 2 0 0 0-2-2h-3\" /><path d=\"M3 16v3a2 2 0 0 0 2 2h3\" /><path d=\"M16 21h3a2 2 0 0 0 2-2v-3\" />","arrow-up":"<path d=\"m5 12 7-7 7 7\" /><path d=\"M12 19V5\" />","arrow-down":"<path d=\"M12 5v14\" /><path d=\"m19 12-7 7-7-7\" />","send":"<path d=\"M14.536 21.686a.5.5 0 0 0 .937-.024l6.5-19a.496.496 0 0 0-.635-.635l-19 6.5a.5.5 0 0 0-.024.937l7.93 3.18a2 2 0 0 1 1.112 1.11z\" /><path d=\"m21.854 2.147-10.94 10.939\" />","image-plus":"<path d=\"M16 5h6\" /><path d=\"M19 2v6\" /><path d=\"M21 11.5V19a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h7.5\" /><path d=\"m21 15-3.086-3.086a2 2 0 0 0-2.828 0L6 21\" /><circle cx=\"9\" cy=\"9\" r=\"2\" />","circle-alert":"<circle cx=\"12\" cy=\"12\" r=\"10\" /><line x1=\"12\" x2=\"12\" y1=\"8\" y2=\"12\" /><line x1=\"12\" x2=\"12.01\" y1=\"16\" y2=\"16\" />","check":"<path d=\"M20 6 9 17l-5-5\" />","monitor-play":"<path d=\"M15.033 9.44a.647.647 0 0 1 0 1.12l-4.065 2.352a.645.645 0 0 1-.968-.56V7.648a.645.645 0 0 1 .967-.56z\" /><path d=\"M12 17v4\" /><path d=\"M8 21h8\" /><rect x=\"2\" y=\"3\" width=\"20\" height=\"14\" rx=\"2\" />","sliders-horizontal":"<path d=\"M10 5H3\" /><path d=\"M12 19H3\" /><path d=\"M14 3v4\" /><path d=\"M16 17v4\" /><path d=\"M21 12h-9\" /><path d=\"M21 19h-5\" /><path d=\"M21 5h-7\" /><path d=\"M8 10v4\" /><path d=\"M8 12H3\" />","loader-circle":"<path d=\"M21 12a9 9 0 1 1-6.219-8.56\" />","panel-bottom":"<rect width=\"18\" height=\"18\" x=\"3\" y=\"3\" rx=\"2\" /><path d=\"M3 15h18\" />","clock":"<circle cx=\"12\" cy=\"12\" r=\"10\" /><path d=\"M12 6v6l4 2\" />","layout-grid":"<rect width=\"7\" height=\"7\" x=\"3\" y=\"3\" rx=\"1\" /><rect width=\"7\" height=\"7\" x=\"14\" y=\"3\" rx=\"1\" /><rect width=\"7\" height=\"7\" x=\"14\" y=\"14\" rx=\"1\" /><rect width=\"7\" height=\"7\" x=\"3\" y=\"14\" rx=\"1\" />","ellipsis":"<circle cx=\"12\" cy=\"12\" r=\"1\" /><circle cx=\"19\" cy=\"12\" r=\"1\" /><circle cx=\"5\" cy=\"12\" r=\"1\" />","pencil":"<path d=\"M21.174 6.812a1 1 0 0 0-3.986-3.987L3.842 16.174a2 2 0 0 0-.5.83l-1.321 4.352a.5.5 0 0 0 .623.622l4.353-1.32a2 2 0 0 0 .83-.497z\" /><path d=\"m15 5 4 4\" />","folder":"<path d=\"M20 20a2 2 0 0 0 2-2V8a2 2 0 0 0-2-2h-7.9a2 2 0 0 1-1.69-.9L9.6 3.9A2 2 0 0 0 7.93 3H4a2 2 0 0 0-2 2v13a2 2 0 0 0 2 2Z\" />","arrow-left":"<path d=\"m12 19-7-7 7-7\" /><path d=\"M19 12H5\" />","library":"<path d=\"m16 6 4 14\" /><path d=\"M12 6v14\" /><path d=\"M8 8v12\" /><path d=\"M4 4v16\" />","rotate-ccw":"<path d=\"M3 12a9 9 0 1 0 9-9 9.75 9.75 0 0 0-6.74 2.74L3 8\" /><path d=\"M3 3v5h5\" />","upload":"<path d=\"M12 3v12\" /><path d=\"m17 8-5-5-5 5\" /><path d=\"M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4\" />","file-plus":"<path d=\"M6 22a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h8a2.4 2.4 0 0 1 1.704.706l3.588 3.588A2.4 2.4 0 0 1 20 8v12a2 2 0 0 1-2 2z\" /><path d=\"M14 2v5a1 1 0 0 0 1 1h5\" /><path d=\"M9 15h6\" /><path d=\"M12 18v-6\" />","moon":"<path d=\"M20.985 12.486a9 9 0 1 1-9.473-9.472c.405-.022.617.46.402.803a6 6 0 0 0 8.268 8.268c.344-.215.825-.004.803.401\" />","sun":"<circle cx=\"12\" cy=\"12\" r=\"4\" /><path d=\"M12 2v2\" /><path d=\"M12 20v2\" /><path d=\"m4.93 4.93 1.41 1.41\" /><path d=\"m17.66 17.66 1.41 1.41\" /><path d=\"M2 12h2\" /><path d=\"M20 12h2\" /><path d=\"m6.34 17.66-1.41 1.41\" /><path d=\"m19.07 4.93-1.41 1.41\" />","folder-plus":"<path d=\"M12 10v6\" /><path d=\"M9 13h6\" /><path d=\"M20 20a2 2 0 0 0 2-2V8a2 2 0 0 0-2-2h-7.9a2 2 0 0 1-1.69-.9L9.6 3.9A2 2 0 0 0 7.93 3H4a2 2 0 0 0-2 2v13a2 2 0 0 0 2 2Z\" />","presentation":"<path d=\"M2 3h20\" /><path d=\"M21 3v11a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V3\" /><path d=\"m7 21 5-5 5 5\" />","server-cog":"<path d=\"m10.852 14.772-.383.923\" /><path d=\"M13.148 14.772a3 3 0 1 0-2.296-5.544l-.383-.923\" /><path d=\"m13.148 9.228.383-.923\" /><path d=\"m13.53 15.696-.382-.924a3 3 0 1 1-2.296-5.544\" /><path d=\"m14.772 10.852.923-.383\" /><path d=\"m14.772 13.148.923.383\" /><path d=\"M4.5 10H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h16a2 2 0 0 1 2 2v4a2 2 0 0 1-2 2h-.5\" /><path d=\"M4.5 14H4a2 2 0 0 0-2 2v4a2 2 0 0 0 2 2h16a2 2 0 0 0 2-2v-4a2 2 0 0 0-2-2h-.5\" /><path d=\"M6 18h.01\" /><path d=\"M6 6h.01\" /><path d=\"m9.228 10.852-.923-.383\" /><path d=\"m9.228 13.148-.923.383\" />","plug-zap":"<path d=\"M6.3 20.3a2.4 2.4 0 0 0 3.4 0L12 18l-6-6-2.3 2.3a2.4 2.4 0 0 0 0 3.4Z\" /><path d=\"m2 22 3-3\" /><path d=\"M7.5 13.5 10 11\" /><path d=\"M10.5 16.5 13 14\" /><path d=\"m18 3-4 4h6l-4 4\" />","graduation-cap":"<path d=\"M21.42 10.922a1 1 0 0 0-.019-1.838L12.83 5.18a2 2 0 0 0-1.66 0L2.6 9.08a1 1 0 0 0 0 1.832l8.57 3.908a2 2 0 0 0 1.66 0z\" /><path d=\"M22 10v6\" /><path d=\"M6 12.5V16a6 3 0 0 0 12 0v-3.5\" />","theater":"<path d=\"M2 10s3-3 3-8\" /><path d=\"M22 10s-3-3-3-8\" /><path d=\"M10 2c0 4.4-3.6 8-8 8\" /><path d=\"M14 2c0 4.4 3.6 8 8 8\" /><path d=\"M2 10s2 2 2 5\" /><path d=\"M22 10s-2 2-2 5\" /><path d=\"M8 15h8\" /><path d=\"M2 22v-1a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v1\" /><path d=\"M14 22v-1a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v1\" />","square":"<rect width=\"18\" height=\"18\" x=\"3\" y=\"3\" rx=\"2\" />","minimize-2":"<path d=\"m14 10 7-7\" /><path d=\"M20 10h-6V4\" /><path d=\"m3 21 7-7\" /><path d=\"M4 14h6v6\" />","braces":"<path d=\"M8 3H7a2 2 0 0 0-2 2v5a2 2 0 0 1-2 2 2 2 0 0 1 2 2v5c0 1.1.9 2 2 2h1\" /><path d=\"M16 21h1a2 2 0 0 0 2-2v-5c0-1.1.9-2 2-2a2 2 0 0 1-2-2V5a2 2 0 0 0-2-2h-1\" />","link":"<path d=\"M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71\" /><path d=\"M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71\" />","paperclip":"<path d=\"m16 6-8.414 8.586a2 2 0 0 0 2.829 2.829l8.414-8.586a4 4 0 1 0-5.657-5.657l-8.379 8.551a6 6 0 1 0 8.485 8.485l8.379-8.551\" />","type":"<path d=\"M12 4v16\" /><path d=\"M4 7V5a1 1 0 0 1 1-1h14a1 1 0 0 1 1 1v2\" /><path d=\"M9 20h6\" />","chevron-left":"<path d=\"m15 18-6-6 6-6\" />","chevron-right":"<path d=\"m9 18 6-6-6-6\" />","maximize-2":"<path d=\"M15 3h6v6\" /><path d=\"m21 3-7 7\" /><path d=\"m3 21 7-7\" /><path d=\"M9 21H3v-6\" />","eye":"<path d=\"M2.062 12.348a1 1 0 0 1 0-.696 10.75 10.75 0 0 1 19.876 0 1 1 0 0 1 0 .696 10.75 10.75 0 0 1-19.876 0\" /><circle cx=\"12\" cy=\"12\" r=\"3\" />","baseline":"<path d=\"M4 20h16\" /><path d=\"m6 16 6-12 6 12\" /><path d=\"M8 12h8\" />","paint-bucket":"<path d=\"M11 7 6 2\" /><path d=\"M18.992 12H2.041\" /><path d=\"M21.145 18.38A3.34 3.34 0 0 1 20 16.5a3.3 3.3 0 0 1-1.145 1.88c-.575.46-.855 1.02-.855 1.595A2 2 0 0 0 20 22a2 2 0 0 0 2-2.025c0-.58-.285-1.13-.855-1.595\" /><path d=\"m8.5 4.5 2.148-2.148a1.205 1.205 0 0 1 1.704 0l7.296 7.296a1.205 1.205 0 0 1 0 1.704l-7.592 7.592a3.615 3.615 0 0 1-5.112 0l-3.888-3.888a3.615 3.615 0 0 1 0-5.112L5.67 7.33\" />","bring-to-front":"<rect x=\"8\" y=\"8\" width=\"8\" height=\"8\" rx=\"2\" /><path d=\"M4 10a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2\" /><path d=\"M14 20a2 2 0 0 0 2 2h4a2 2 0 0 0 2-2v-4a2 2 0 0 0-2-2\" />","send-to-back":"<rect x=\"14\" y=\"14\" width=\"8\" height=\"8\" rx=\"2\" /><rect x=\"2\" y=\"2\" width=\"8\" height=\"8\" rx=\"2\" /><path d=\"M7 14v1a2 2 0 0 0 2 2h1\" /><path d=\"M14 7h1a2 2 0 0 1 2 2v1\" />","settings":"<path d=\"M9.671 4.136a2.34 2.34 0 0 1 4.659 0 2.34 2.34 0 0 0 3.319 1.915 2.34 2.34 0 0 1 2.33 4.033 2.34 2.34 0 0 0 0 3.831 2.34 2.34 0 0 1-2.33 4.033 2.34 2.34 0 0 0-3.319 1.915 2.34 2.34 0 0 1-4.659 0 2.34 2.34 0 0 0-3.32-1.915 2.34 2.34 0 0 1-2.33-4.033 2.34 2.34 0 0 0 0-3.831A2.34 2.34 0 0 1 6.35 6.051a2.34 2.34 0 0 0 3.319-1.915\" /><circle cx=\"12\" cy=\"12\" r=\"3\" />","swatch-book":"<path d=\"M11 17a4 4 0 0 1-8 0V5a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2Z\" /><path d=\"M16.7 13H19a2 2 0 0 1 2 2v4a2 2 0 0 1-2 2H7\" /><path d=\"M 7 17h.01\" /><path d=\"m11 8 2.3-2.3a2.4 2.4 0 0 1 3.404.004L18.6 7.6a2.4 2.4 0 0 1 .026 3.434L9.9 19.8\" />","stamp":"<path d=\"M14 13V8.5C14 7 15 7 15 5a3 3 0 0 0-6 0c0 2 1 2 1 3.5V13\" /><path d=\"M20 15.5a2.5 2.5 0 0 0-2.5-2.5h-11A2.5 2.5 0 0 0 4 15.5V17a1 1 0 0 0 1 1h14a1 1 0 0 0 1-1z\" /><path d=\"M5 22h14\" />","git-compare":"<circle cx=\"18\" cy=\"18\" r=\"3\" /><circle cx=\"6\" cy=\"6\" r=\"3\" /><path d=\"M13 6h3a2 2 0 0 1 2 2v7\" /><path d=\"M11 18H8a2 2 0 0 1-2-2V9\" />","bookmark-plus":"<path d=\"M12 7v6\" /><path d=\"M15 10H9\" /><path d=\"M17 3a2 2 0 0 1 2 2v15a1 1 0 0 1-1.496.868l-4.512-2.578a2 2 0 0 0-1.984 0l-4.512 2.578A1 1 0 0 1 5 20V5a2 2 0 0 1 2-2z\" />","undo-2":"<path d=\"M9 14 4 9l5-5\" /><path d=\"M4 9h10.5a5.5 5.5 0 0 1 5.5 5.5a5.5 5.5 0 0 1-5.5 5.5H11\" />","redo-2":"<path d=\"m15 14 5-5-5-5\" /><path d=\"M20 9H9.5A5.5 5.5 0 0 0 4 14.5A5.5 5.5 0 0 0 9.5 20H13\" />","align-start-vertical":"<rect width=\"9\" height=\"6\" x=\"6\" y=\"14\" rx=\"2\" /><rect width=\"16\" height=\"6\" x=\"6\" y=\"4\" rx=\"2\" /><path d=\"M2 2v20\" />","align-center-vertical":"<path d=\"M12 2v20\" /><path d=\"M8 10H4a2 2 0 0 1-2-2V6c0-1.1.9-2 2-2h4\" /><path d=\"M16 10h4a2 2 0 0 0 2-2V6a2 2 0 0 0-2-2h-4\" /><path d=\"M8 20H7a2 2 0 0 1-2-2v-2c0-1.1.9-2 2-2h1\" /><path d=\"M16 14h1a2 2 0 0 1 2 2v2a2 2 0 0 1-2 2h-1\" />","align-end-vertical":"<rect width=\"16\" height=\"6\" x=\"2\" y=\"4\" rx=\"2\" /><rect width=\"9\" height=\"6\" x=\"9\" y=\"14\" rx=\"2\" /><path d=\"M22 22V2\" />","align-start-horizontal":"<rect width=\"6\" height=\"16\" x=\"4\" y=\"6\" rx=\"2\" /><rect width=\"6\" height=\"9\" x=\"14\" y=\"6\" rx=\"2\" /><path d=\"M22 2H2\" />","align-center-horizontal":"<path d=\"M2 12h20\" /><path d=\"M10 16v4a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2v-4\" /><path d=\"M10 8V4a2 2 0 0 0-2-2H6a2 2 0 0 0-2 2v4\" /><path d=\"M20 16v1a2 2 0 0 1-2 2h-2a2 2 0 0 1-2-2v-1\" /><path d=\"M14 8V7c0-1.1.9-2 2-2h2a2 2 0 0 1 2 2v1\" />","align-end-horizontal":"<rect width=\"6\" height=\"16\" x=\"4\" y=\"2\" rx=\"2\" /><rect width=\"6\" height=\"9\" x=\"14\" y=\"9\" rx=\"2\" /><path d=\"M22 22H2\" />","align-horizontal-distribute-center":"<rect width=\"6\" height=\"14\" x=\"4\" y=\"5\" rx=\"2\" /><rect width=\"6\" height=\"10\" x=\"14\" y=\"7\" rx=\"2\" /><path d=\"M17 22v-5\" /><path d=\"M17 7V2\" /><path d=\"M7 22v-3\" /><path d=\"M7 5V2\" />","align-vertical-distribute-center":"<path d=\"M22 17h-3\" /><path d=\"M22 7h-5\" /><path d=\"M5 17H2\" /><path d=\"M7 7H2\" /><rect x=\"5\" y=\"14\" width=\"14\" height=\"6\" rx=\"2\" /><rect x=\"7\" y=\"4\" width=\"10\" height=\"6\" rx=\"2\" />","paintbrush":"<path d=\"m14.622 17.897-10.68-2.913\" /><path d=\"M18.376 2.622a1 1 0 1 1 3.002 3.002L17.36 9.643a.5.5 0 0 0 0 .707l.944.944a2.41 2.41 0 0 1 0 3.408l-.944.944a.5.5 0 0 1-.707 0L8.354 7.348a.5.5 0 0 1 0-.707l.944-.944a2.41 2.41 0 0 1 3.408 0l.944.944a.5.5 0 0 0 .707 0z\" /><path d=\"M9 8c-1.804 2.71-3.97 3.46-6.583 3.948a.507.507 0 0 0-.302.819l7.32 8.883a1 1 0 0 0 1.185.204C12.735 20.405 16 16.792 16 15\" />","clipboard-paste":"<path d=\"M11 14h10\" /><path d=\"M16 4h2a2 2 0 0 1 2 2v1.344\" /><path d=\"m17 18 4-4-4-4\" /><path d=\"M8 4H6a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h12a2 2 0 0 0 1.793-1.113\" /><rect x=\"8\" y=\"2\" width=\"8\" height=\"4\" rx=\"1\" />","lock":"<rect width=\"18\" height=\"11\" x=\"3\" y=\"11\" rx=\"2\" ry=\"2\" /><path d=\"M7 11V7a5 5 0 0 1 10 0v4\" />","lock-open":"<rect width=\"18\" height=\"11\" x=\"3\" y=\"11\" rx=\"2\" ry=\"2\" /><path d=\"M7 11V7a5 5 0 0 1 9.9-1\" />","eye-off":"<path d=\"M10.733 5.076a10.744 10.744 0 0 1 11.205 6.575 1 1 0 0 1 0 .696 10.747 10.747 0 0 1-1.444 2.49\" /><path d=\"M14.084 14.158a3 3 0 0 1-4.242-4.242\" /><path d=\"M17.479 17.499a10.75 10.75 0 0 1-15.417-5.151 1 1 0 0 1 0-.696 10.75 10.75 0 0 1 4.446-5.143\" /><path d=\"m2 2 20 20\" />","share-2":"<circle cx=\"18\" cy=\"5\" r=\"3\" /><circle cx=\"6\" cy=\"12\" r=\"3\" /><circle cx=\"18\" cy=\"19\" r=\"3\" /><line x1=\"8.59\" x2=\"15.42\" y1=\"13.51\" y2=\"17.49\" /><line x1=\"15.41\" x2=\"8.59\" y1=\"6.51\" y2=\"10.49\" />","globe":"<circle cx=\"12\" cy=\"12\" r=\"10\" /><path d=\"M12 2a14.5 14.5 0 0 0 0 20 14.5 14.5 0 0 0 0-20\" /><path d=\"M2 12h20\" />"};
@@ -0,0 +1,372 @@
1
+ /* Visualizadores do explorador (window.SagaViewers), leves e sem dependência de fora:
2
+ - codeEditor: editor de texto com números de linha e realce por linguagem (json, yaml, md, js/ts, py, css, html,
3
+ xml/svg, sql, sh, ini, csv/tsv com cada coluna de uma cor)
4
+ - pdfView: páginas do PDF (pdf.js servido pelo Studio; sem ele, o leitor do navegador)
5
+ - docxView: o .docx convertido em HTML pelo servidor (só leitura)
6
+ - sheetGrid: planilha como no Excel (letras nas colunas, números nas linhas, editar, colar do Excel, desfazer) */
7
+ (function () {
8
+ const esc = (s) => String(s ?? "").replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;");
9
+
10
+ // ------------------------------------------------------------------ linguagem pelo nome
11
+ const EXT_LANG = { json: "json", yaml: "yaml", yml: "yaml", md: "md", markdown: "md", js: "js", mjs: "js", cjs: "js", jsx: "js", ts: "js", tsx: "js", py: "py", css: "css", html: "html", htm: "html", xml: "xml", svg: "xml", sql: "sql", sh: "sh", bash: "sh", bat: "sh", ps1: "sh", ini: "ini", toml: "ini", cfg: "ini", csv: "csv", tsv: "tsv", java: "c", c: "c", h: "c", cpp: "c", cs: "c", go: "c", rs: "c", r: "py", m: "m", tex: "tex", bib: "tex" };
12
+ const langOf = (name) => EXT_LANG[(String(name).match(/\.([a-z0-9]+)$/i)?.[1] || "").toLowerCase()] || "plain";
13
+
14
+ const KW = {
15
+ js: "break case catch class const continue debugger default delete do else export extends finally for function if import in instanceof let new return super switch this throw try typeof var void while with yield async await of static get set null true false undefined from as interface type enum implements",
16
+ py: "False None True and as assert async await break class continue def del elif else except finally for from global if import in is lambda nonlocal not or pass raise return try while with yield self",
17
+ c: "auto break case char const continue default do double else enum extern float for goto if int long register return short signed sizeof static struct switch typedef union unsigned void volatile while class public private protected new delete this try catch throw namespace using bool true false null package import func var let fn mut impl pub struct string",
18
+ sh: "if then else elif fi for while do done case esac function in echo export local return exit set cd ls rm cp mv mkdir sudo param foreach",
19
+ sql: "select from where group by order having insert into values update set delete create table drop alter join left right inner outer full on as and or not null is in like limit offset distinct union all case when then else end primary key foreign references index view",
20
+ m: "function end if elseif else for while switch case otherwise break continue return global persistent try catch",
21
+ };
22
+ const COMMENT = { js: ["//", "/*"], c: ["//", "/*"], py: ["#"], sh: ["#"], sql: ["--", "/*"], m: ["%"], ini: ["#", ";"], tex: ["%"] };
23
+ const span = (cls, s) => `<span class="hl-${cls}">${esc(s)}</span>`;
24
+
25
+ function codeHL(text, lang) {
26
+ const kw = new Set((KW[lang] || "").split(" "));
27
+ const cm = COMMENT[lang] || [];
28
+ const parts = [];
29
+ if (cm.includes("/*")) parts.push(String.raw`\/\*[\s\S]*?(?:\*\/|$)`);
30
+ for (const c of cm.filter((c) => c !== "/*")) parts.push(`${c.replace(/[-/\\^$*+?.()|[\]{}]/g, "\\$&")}[^\\n]*`);
31
+ const commentRe = parts.join("|") || "(?!)";
32
+ const strRe = lang === "py" ? String.raw`"""[\s\S]*?(?:"""|$)|'''[\s\S]*?(?:'''|$)|[rbfu]{0,2}"(?:\\.|[^"\\\n])*"?|[rbfu]{0,2}'(?:\\.|[^'\\\n])*'?`
33
+ : lang === "js" ? String.raw`\x60(?:\\[\s\S]|[^\x60\\])*\x60?|"(?:\\.|[^"\\\n])*"?|'(?:\\.|[^'\\\n])*'?`
34
+ : String.raw`"(?:\\.|[^"\\\n])*"?|'(?:\\.|[^'\\\n])*'?`;
35
+ const re = new RegExp(`(${commentRe})|(${strRe})|(\\b0x[0-9a-fA-F]+\\b|\\b\\d[\\d_]*(?:\\.\\d+)?(?:[eE][+-]?\\d+)?\\b)|([A-Za-z_$][\\w$]*)|(@[A-Za-z_]\\w*)`, "g");
36
+ let out = "", last = 0, m;
37
+ while ((m = re.exec(text))) {
38
+ if (m.index === re.lastIndex) { re.lastIndex++; continue; }
39
+ out += esc(text.slice(last, m.index));
40
+ if (m[1]) out += span("com", m[1]);
41
+ else if (m[2]) out += span("str", m[2]);
42
+ else if (m[3]) out += span("num", m[3]);
43
+ else if (m[4]) out += kw.has(lang === "sql" ? m[4].toLowerCase() : m[4]) ? span("kw", m[4]) : /^\s*\(/.test(text.slice(re.lastIndex, re.lastIndex + 40)) ? span("fn", m[4]) : esc(m[4]);
44
+ else if (m[5]) out += span("dec", m[5]);
45
+ last = re.lastIndex;
46
+ }
47
+ return out + esc(text.slice(last));
48
+ }
49
+ function jsonHL(text) {
50
+ return text.replace(/("(?:\\.|[^"\\])*")(\s*:)?|\b(true|false|null)\b|(-?\b\d+(?:\.\d+)?(?:[eE][+-]?\d+)?\b)|([&<>])/g, (all, s, colon, lit, num, ch) => {
51
+ if (s) return colon ? span("key", s) + colon : span("str", s);
52
+ if (lit) return span("kw", lit);
53
+ if (num) return span("num", num);
54
+ return esc(ch);
55
+ });
56
+ }
57
+ function yamlHL(text) {
58
+ return text.split("\n").map((line) => {
59
+ if (/^\s*#/.test(line)) return span("com", line);
60
+ const m = /^(\s*)(- )?([^\s:#][^:#]*?)(:)(\s.*)?$/.exec(line);
61
+ const val = (v) => {
62
+ const [body, com] = (() => { const k = v.search(/\s#/); return k >= 0 ? [v.slice(0, k), v.slice(k)] : [v, ""]; })();
63
+ let h = /^\s*(true|false|null|~|yes|no)\s*$/i.test(body) ? span("kw", body) : /^\s*-?\d+(\.\d+)?\s*$/.test(body) ? span("num", body) : /^\s*["']/.test(body) ? span("str", body) : esc(body);
64
+ return h + (com ? span("com", com) : "");
65
+ };
66
+ if (m) return `${m[1]}${m[2] ? span("punc", "- ") : ""}${span("key", m[3])}${m[4]}${m[5] ? val(m[5]) : ""}`;
67
+ const d = /^(\s*)(- )(.*)$/.exec(line);
68
+ if (d) return `${d[1]}${span("punc", "- ")}${val(d[3])}`;
69
+ return val(line);
70
+ }).join("\n");
71
+ }
72
+ function mdHL(text) {
73
+ let fence = false;
74
+ return text.split("\n").map((line) => {
75
+ if (/^\s*(```|~~~)/.test(line)) { fence = !fence; return span("com", line); }
76
+ if (fence) return span("str", line);
77
+ if (/^#{1,6}\s/.test(line)) return span("key", line);
78
+ if (/^\s*>/.test(line)) return span("com", line);
79
+ let h = esc(line);
80
+ h = h.replace(/^(\s*)([-*+]|\d+[.)])(\s)/, (a, s, b, c) => `${s}<span class="hl-punc">${b}</span>${c}`);
81
+ h = h.replace(/(`[^`]+`)/g, '<span class="hl-str">$1</span>').replace(/(\*\*[^*]+\*\*|__[^_]+__)/g, '<span class="hl-kw">$1</span>').replace(/(\[[^\]]+\]\([^)]+\))/g, '<span class="hl-fn">$1</span>');
82
+ return h;
83
+ }).join("\n");
84
+ }
85
+ function markupHL(text) {
86
+ return text.replace(/(<!--[\s\S]*?(?:-->|$))|(<\/?)([\w:.-]+)((?:\s+[\w:.-]+(?:\s*=\s*(?:"[^"]*"|'[^']*'|[^\s>]+))?)*)(\s*\/?>)?|([&<>])/g, (all, com, open, tag, attrs, close, ch) => {
87
+ if (com) return span("com", com);
88
+ if (tag) {
89
+ const a = (attrs || "").replace(/([\w:.-]+)(\s*=\s*)?("[^"]*"|'[^']*'|[^\s>]+)?/g, (x, n, eq, v) => (n ? span("fn", n) : "") + (eq ? esc(eq) : "") + (v ? span("str", v) : ""));
90
+ return span("punc", open) + span("kw", tag) + a + (close ? span("punc", close) : "");
91
+ }
92
+ return esc(ch);
93
+ });
94
+ }
95
+ function cssHL(text) {
96
+ return text.replace(/(\/\*[\s\S]*?(?:\*\/|$))|("[^"]*"|'[^']*')|(#[0-9a-fA-F]{3,8}\b|-?\d*\.?\d+(?:px|em|rem|%|vh|vw|s|ms|deg|fr)?\b)|([\w-]+)(\s*:)|([&<>])/g, (all, com, str, num, prop, colon, ch) => {
97
+ if (com) return span("com", com);
98
+ if (str) return span("str", str);
99
+ if (num) return span("num", num);
100
+ if (prop) return span("key", prop) + colon;
101
+ return esc(ch);
102
+ });
103
+ }
104
+ function iniHL(text) {
105
+ return text.split("\n").map((l) => {
106
+ if (/^\s*[#;]/.test(l)) return span("com", l);
107
+ if (/^\s*\[.*\]\s*$/.test(l)) return span("kw", l);
108
+ const m = l.match(/^(\s*[^=:\s][^=:]*?)(\s*[=:])(.*)$/);
109
+ return m ? span("key", m[1]) + esc(m[2]) + span("str", m[3]) : esc(l);
110
+ }).join("\n");
111
+ }
112
+ // CSV: cada coluna de uma cor (como o Rainbow CSV do VS Code), respeitando aspas
113
+ function csvHL(text, delim) {
114
+ const d = delim || (window.SagaCSV ? window.SagaCSV.detect(text) : ",");
115
+ let out = "", col = 0, q = false, cell = "";
116
+ const flush = () => { if (cell) out += `<span class="hl-c${col % 8}">${esc(cell)}</span>`; cell = ""; };
117
+ for (let i = 0; i < text.length; i++) {
118
+ const c = text[i];
119
+ if (c === '"') { q = !q; cell += c; continue; }
120
+ if (!q && c === d) { flush(); out += `<span class="hl-punc">${esc(c)}</span>`; col++; continue; }
121
+ if (!q && c === "\n") { flush(); out += "\n"; col = 0; continue; }
122
+ cell += c;
123
+ }
124
+ flush();
125
+ return out;
126
+ }
127
+ function highlight(lang, text, opts = {}) {
128
+ if (text.length > 400000) return esc(text);
129
+ switch (lang) {
130
+ case "json": return jsonHL(text);
131
+ case "yaml": return yamlHL(text);
132
+ case "md": return mdHL(text);
133
+ case "html": case "xml": return markupHL(text);
134
+ case "css": return cssHL(text);
135
+ case "ini": return iniHL(text);
136
+ case "csv": return csvHL(text, opts.delimiter);
137
+ case "tsv": return csvHL(text, "\t");
138
+ case "plain": return esc(text);
139
+ default: return codeHL(text, lang);
140
+ }
141
+ }
142
+
143
+ // ------------------------------------------------------------------ editor de código
144
+ function codeEditor({ text = "", lang = "plain", readOnly = false, onInput, highlighter } = {}) {
145
+ const wrap = document.createElement("div");
146
+ wrap.className = "cv-editor";
147
+ wrap.innerHTML = `<div class="cv-gutter" aria-hidden="true"></div><div class="cv-area"><pre class="cv-hl" aria-hidden="true"></pre><textarea class="cv-text" spellcheck="false" wrap="off"${readOnly ? " readonly" : ""}></textarea></div>`;
148
+ const ta = wrap.querySelector("textarea"), hl = wrap.querySelector("pre"), gutter = wrap.querySelector(".cv-gutter");
149
+ ta.value = text;
150
+ let lines = -1, raf = 0;
151
+ const paint = () => {
152
+ raf = 0;
153
+ const v = ta.value;
154
+ hl.innerHTML = (highlighter ? highlighter(v) : highlight(lang, v)) + "\n";
155
+ const n = v.split("\n").length;
156
+ if (n !== lines) { lines = n; gutter.innerHTML = Array.from({ length: n }, (_, i) => `<div>${i + 1}</div>`).join(""); }
157
+ sync();
158
+ };
159
+ const sync = () => { hl.scrollTop = ta.scrollTop; hl.scrollLeft = ta.scrollLeft; gutter.scrollTop = ta.scrollTop; };
160
+ ta.addEventListener("scroll", sync);
161
+ ta.addEventListener("input", () => { if (!raf) raf = requestAnimationFrame(paint); onInput?.(ta.value); });
162
+ ta.addEventListener("keydown", (ev) => {
163
+ if (ev.key === "Tab" && !readOnly) { // Tab indenta como no VS Code (Shift+Tab tira)
164
+ ev.preventDefault();
165
+ const { selectionStart: a, selectionEnd: b, value: v } = ta;
166
+ const ind = lang === "py" || lang === "c" ? " " : " ";
167
+ if (!ev.shiftKey && a === b) { ta.setRangeText(ind, a, b, "end"); }
168
+ else {
169
+ const ls = v.lastIndexOf("\n", a - 1) + 1, block = v.slice(ls, b);
170
+ const next = ev.shiftKey ? block.replace(/^( {1,4}|\t)/gm, "") : block.replace(/^/gm, ind);
171
+ ta.setRangeText(next, ls, b, "select");
172
+ }
173
+ ta.dispatchEvent(new Event("input"));
174
+ }
175
+ });
176
+ paint();
177
+ return { wrap, ta, paint, setText: (t) => { ta.value = t; paint(); } };
178
+ }
179
+
180
+ // ------------------------------------------------------------------ PDF
181
+ let pdfjs = null;
182
+ async function loadPdfjs() {
183
+ if (pdfjs) return pdfjs;
184
+ const mod = await import(new URL("vendor/pdf.min.mjs", location.href).href);
185
+ mod.GlobalWorkerOptions.workerSrc = new URL("vendor/pdf.worker.min.mjs", location.href).href;
186
+ pdfjs = mod;
187
+ return mod;
188
+ }
189
+ async function pdfView(host, url, { name = "" } = {}) {
190
+ host.innerHTML = `<div class="pv-bar"><span class="pv-count">abrindo…</span><span class="pv-grow"></span><button type="button" class="btn btn-small" data-zoom="-1" title="Diminuir"><i class="ic" data-ic="zoom-out"></i></button><span class="pv-zoom">100%</span><button type="button" class="btn btn-small" data-zoom="1" title="Aumentar"><i class="ic" data-ic="zoom-in"></i></button><button type="button" class="btn btn-small" data-zoom="0" title="Largura da tela"><i class="ic" data-ic="maximize-2"></i></button></div><div class="pv-pages"></div>`;
191
+ const pages = host.querySelector(".pv-pages");
192
+ let lib;
193
+ try { lib = await loadPdfjs(); }
194
+ catch { host.innerHTML = `<iframe class="pv-native" src="${esc(url)}" title="${esc(name)}"></iframe>`; return; }
195
+ const doc = await lib.getDocument({ url, isEvalSupported: false }).promise;
196
+ host.querySelector(".pv-count").textContent = `${doc.numPages} ${doc.numPages === 1 ? "página" : "páginas"}`;
197
+ const first = await doc.getPage(1);
198
+ const base = first.getViewport({ scale: 1 });
199
+ let zoom = 0; // 0 = largura da tela
200
+ const scaleNow = () => (zoom || Math.max(0.3, (pages.clientWidth - 48) / base.width));
201
+ const slots = [];
202
+ for (let i = 1; i <= doc.numPages; i++) {
203
+ const slot = document.createElement("div");
204
+ slot.className = "pv-page"; slot.dataset.page = i;
205
+ pages.append(slot); slots.push(slot);
206
+ }
207
+ const drawn = new Map();
208
+ const layout = () => {
209
+ const s = scaleNow();
210
+ host.querySelector(".pv-zoom").textContent = `${Math.round(s * 100)}%`;
211
+ for (const slot of slots) { slot.style.width = `${base.width * s}px`; slot.style.height = `${base.height * s}px`; }
212
+ drawn.clear(); slots.forEach((sl) => (sl.innerHTML = ""));
213
+ io.disconnect(); slots.forEach((sl) => io.observe(sl));
214
+ };
215
+ const draw = async (slot) => {
216
+ const n = +slot.dataset.page, s = scaleNow();
217
+ if (drawn.get(n) === s) return;
218
+ drawn.set(n, s);
219
+ const page = await doc.getPage(n);
220
+ const vp = page.getViewport({ scale: s * (window.devicePixelRatio || 1) });
221
+ const c = document.createElement("canvas");
222
+ c.width = vp.width; c.height = vp.height;
223
+ await page.render({ canvasContext: c.getContext("2d"), viewport: vp }).promise;
224
+ if (drawn.get(n) !== s) return;
225
+ slot.innerHTML = ""; slot.append(c);
226
+ };
227
+ const io = new IntersectionObserver((es) => es.forEach((e) => e.isIntersecting && draw(e.target)), { root: pages, rootMargin: "600px 0px" });
228
+ host.querySelectorAll("[data-zoom]").forEach((b) => (b.onclick = () => {
229
+ const d = +b.dataset.zoom;
230
+ zoom = d === 0 ? 0 : Math.min(4, Math.max(0.25, (zoom || scaleNow()) * (d > 0 ? 1.25 : 0.8)));
231
+ layout();
232
+ }));
233
+ new ResizeObserver(() => { if (!zoom) layout(); }).observe(pages);
234
+ layout();
235
+ return { doc };
236
+ }
237
+
238
+ // ------------------------------------------------------------------ DOCX (HTML vindo do servidor)
239
+ function docxView(host, html) {
240
+ host.innerHTML = `<div class="dx-scroll"><article class="dx-page">${html || '<p class="dx-empty">Documento sem texto.</p>'}</article></div>`;
241
+ }
242
+
243
+ // ------------------------------------------------------------------ planilha como no Excel
244
+ const colName = (i) => { let s = ""; i++; while (i > 0) { const r = (i - 1) % 26; s = String.fromCharCode(65 + r) + s; i = Math.floor((i - 1) / 26); } return s; };
245
+ const looksNum = (v) => /^\s*[-+]?(R\$\s*)?(\d{1,3}(\.\d{3})+(,\d+)?|\d+([.,]\d+)?)\s*%?\s*$/.test(String(v ?? ""));
246
+ function sheetGrid(host, { rows, editable = false, hasHeader = false, maxRender = 3000, onChange, types = [] } = {}) {
247
+ let data = rows.map((r) => [...r]);
248
+ const undo = [], redo = [];
249
+ let sel = { r: 0, c: 0, r2: 0, c2: 0 }, editing = null;
250
+ host.innerHTML = `<div class="sg-wrap" tabindex="0"><table class="sg"></table></div>`;
251
+ const wrap = host.querySelector(".sg-wrap"), table = host.querySelector("table");
252
+ const width = () => Math.max(1, ...data.map((r) => r.length));
253
+ const snapshot = () => { undo.push(JSON.stringify(data)); if (undo.length > 100) undo.shift(); redo.length = 0; };
254
+ const changed = () => { render(); onChange?.(data); };
255
+ function render() {
256
+ const W = width(), R = Math.min(data.length, maxRender);
257
+ const colW = Array.from({ length: W }, (_, c) => Math.min(280, Math.max(64, 9 + 7.2 * Math.max(...data.slice(0, 200).map((r) => String(r[c] ?? "").length), 1))));
258
+ table.innerHTML = `<colgroup><col class="sg-n-col">${colW.map((w) => `<col style="width:${w}px">`).join("")}</colgroup>
259
+ <thead><tr><th class="sg-corner"></th>${Array.from({ length: W }, (_, c) => `<th data-col="${c}">${colName(c)}${types[c] ? `<span class="sh-type t-${types[c].type}">${esc(types[c].label)}</span>` : ""}</th>`).join("")}</tr></thead>
260
+ <tbody>${data.slice(0, R).map((r, i) => `<tr${hasHeader && i === 0 ? ' class="sg-head"' : ""}><th data-row="${i}">${i + 1}</th>${Array.from({ length: W }, (_, c) => { const v = r[c] ?? ""; return `<td data-r="${i}" data-c="${c}"${looksNum(v) && !(hasHeader && i === 0) ? ' class="num"' : ""}>${esc(v)}</td>`; }).join("")}</tr>`).join("")}</tbody>`;
261
+ paintSel();
262
+ }
263
+ const cell = (r, c) => table.querySelector(`td[data-r="${r}"][data-c="${c}"]`);
264
+ function paintSel() {
265
+ table.querySelectorAll(".sel, .cur").forEach((e) => e.classList.remove("sel", "cur"));
266
+ table.querySelectorAll("th.on").forEach((e) => e.classList.remove("on"));
267
+ const [r1, r2] = [Math.min(sel.r, sel.r2), Math.max(sel.r, sel.r2)], [c1, c2] = [Math.min(sel.c, sel.c2), Math.max(sel.c, sel.c2)];
268
+ for (let r = r1; r <= r2; r++) for (let c = c1; c <= c2; c++) cell(r, c)?.classList.add("sel");
269
+ const cur = cell(sel.r, sel.c); cur?.classList.add("cur");
270
+ for (let c = c1; c <= c2; c++) table.querySelector(`thead th[data-col="${c}"]`)?.classList.add("on");
271
+ for (let r = r1; r <= r2; r++) table.querySelector(`tbody th[data-row="${r}"]`)?.classList.add("on");
272
+ cur?.scrollIntoView({ block: "nearest", inline: "nearest" });
273
+ }
274
+ const setCell = (r, c, v) => { while (data.length <= r) data.push(Array(width()).fill("")); const row = data[r]; while (row.length <= c) row.push(""); row[c] = v; };
275
+ function startEdit(initial) {
276
+ if (!editable) return;
277
+ const td = cell(sel.r, sel.c); if (!td) return;
278
+ const inp = document.createElement("input");
279
+ inp.className = "sg-input"; inp.value = initial ?? (data[sel.r]?.[sel.c] ?? "");
280
+ td.textContent = ""; td.append(inp); inp.focus();
281
+ if (initial == null) inp.select(); else inp.setSelectionRange(inp.value.length, inp.value.length);
282
+ editing = { inp, r: sel.r, c: sel.c };
283
+ inp.addEventListener("keydown", (ev) => {
284
+ if (ev.key === "Enter" || ev.key === "Tab") { ev.preventDefault(); commit(); move(ev.key === "Enter" ? (ev.shiftKey ? -1 : 1) : 0, ev.key === "Tab" ? (ev.shiftKey ? -1 : 1) : 0); }
285
+ else if (ev.key === "Escape") { ev.preventDefault(); editing = null; render(); wrap.focus(); }
286
+ ev.stopPropagation();
287
+ });
288
+ inp.addEventListener("blur", () => editing && commit());
289
+ }
290
+ function commit() {
291
+ const e = editing; if (!e) return;
292
+ editing = null;
293
+ if ((data[e.r]?.[e.c] ?? "") !== e.inp.value) { snapshot(); setCell(e.r, e.c, e.inp.value); changed(); } else render();
294
+ wrap.focus();
295
+ }
296
+ function move(dr, dc, extend = false) {
297
+ const r = Math.max(0, Math.min(data.length - (editable ? 0 : 1), sel.r2 + dr)), c = Math.max(0, Math.min(width() - (editable ? 0 : 1), sel.c2 + dc));
298
+ if (extend) { sel.r2 = r; sel.c2 = c; } else sel = { r, c, r2: r, c2: c };
299
+ if (r >= data.length || c >= width()) { setCell(r, c, data[r]?.[c] ?? ""); render(); } else paintSel();
300
+ }
301
+ const range = () => { const [r1, r2] = [Math.min(sel.r, sel.r2), Math.max(sel.r, sel.r2)], [c1, c2] = [Math.min(sel.c, sel.c2), Math.max(sel.c, sel.c2)]; return { r1, r2, c1, c2 }; };
302
+ table.addEventListener("mousedown", (ev) => {
303
+ const td = ev.target.closest("td"), th = ev.target.closest("th");
304
+ if (td && !td.querySelector("input")) {
305
+ const r = +td.dataset.r, c = +td.dataset.c;
306
+ if (ev.shiftKey) { sel.r2 = r; sel.c2 = c; } else sel = { r, c, r2: r, c2: c };
307
+ paintSel(); wrap.focus(); ev.preventDefault();
308
+ const over = (e2) => { const t2 = e2.target.closest?.("td"); if (t2) { sel.r2 = +t2.dataset.r; sel.c2 = +t2.dataset.c; paintSel(); } };
309
+ table.addEventListener("mouseover", over);
310
+ window.addEventListener("mouseup", () => table.removeEventListener("mouseover", over), { once: true });
311
+ } else if (th?.dataset.col) { const c = +th.dataset.col; sel = { r: 0, c, r2: data.length - 1, c2: c }; paintSel(); wrap.focus(); }
312
+ else if (th?.dataset.row) { const r = +th.dataset.row; sel = { r, c: 0, r2: r, c2: width() - 1 }; paintSel(); wrap.focus(); }
313
+ });
314
+ table.addEventListener("dblclick", (ev) => { if (ev.target.closest("td")) startEdit(); });
315
+ wrap.addEventListener("keydown", (ev) => {
316
+ if (editing) return;
317
+ const k = ev.key, mod = ev.ctrlKey || ev.metaKey;
318
+ const arrows = { ArrowUp: [-1, 0], ArrowDown: [1, 0], ArrowLeft: [0, -1], ArrowRight: [0, 1] };
319
+ if (arrows[k]) { ev.preventDefault(); move(...arrows[k], ev.shiftKey); }
320
+ else if (k === "Enter") { ev.preventDefault(); if (editable && !ev.shiftKey) startEdit(); else move(ev.shiftKey ? -1 : 1, 0); }
321
+ else if (k === "Tab") { ev.preventDefault(); move(0, ev.shiftKey ? -1 : 1); }
322
+ else if (k === "F2") { ev.preventDefault(); startEdit(); }
323
+ else if ((k === "Delete" || k === "Backspace") && editable) {
324
+ ev.preventDefault(); snapshot();
325
+ const { r1, r2, c1, c2 } = range();
326
+ for (let r = r1; r <= r2; r++) for (let c = c1; c <= c2; c++) if (data[r] && c < data[r].length) data[r][c] = "";
327
+ changed();
328
+ } else if (mod && k.toLowerCase() === "z" && editable) { ev.preventDefault(); if (undo.length) { redo.push(JSON.stringify(data)); data = JSON.parse(undo.pop()); changed(); } }
329
+ else if (mod && k.toLowerCase() === "y" && editable) { ev.preventDefault(); if (redo.length) { undo.push(JSON.stringify(data)); data = JSON.parse(redo.pop()); changed(); } }
330
+ else if (mod && k.toLowerCase() === "a") { ev.preventDefault(); sel = { r: 0, c: 0, r2: data.length - 1, c2: width() - 1 }; paintSel(); }
331
+ else if (editable && k.length === 1 && !mod && !ev.altKey) { ev.preventDefault(); startEdit(k); }
332
+ });
333
+ // copiar e colar no formato do Excel (tab entre colunas, quebra entre linhas)
334
+ wrap.addEventListener("copy", (ev) => {
335
+ if (editing) return;
336
+ const { r1, r2, c1, c2 } = range();
337
+ const tsv = data.slice(r1, r2 + 1).map((r) => Array.from({ length: c2 - c1 + 1 }, (_, k) => r[c1 + k] ?? "").join("\t")).join("\n");
338
+ ev.clipboardData.setData("text/plain", tsv); ev.preventDefault();
339
+ });
340
+ wrap.addEventListener("paste", (ev) => {
341
+ if (editing || !editable) return;
342
+ const text = ev.clipboardData.getData("text/plain"); if (!text) return;
343
+ ev.preventDefault(); snapshot();
344
+ const block = window.SagaCSV ? window.SagaCSV.parse(text, text.includes("\t") ? "\t" : undefined).rows : text.split(/\r?\n/).map((l) => l.split("\t"));
345
+ block.forEach((row, i) => row.forEach((v, j) => setCell(sel.r + i, sel.c + j, v)));
346
+ sel.r2 = sel.r + block.length - 1; sel.c2 = sel.c + Math.max(...block.map((r) => r.length)) - 1;
347
+ changed();
348
+ });
349
+ // botão direito: linhas e colunas, como no Excel
350
+ host.addEventListener("contextmenu", (ev) => {
351
+ const td = ev.target.closest("td, th"); if (!td || !editable || !window.SagaViewers.contextMenu) return;
352
+ ev.preventDefault();
353
+ if (td.dataset.r != null && !(+td.dataset.r >= Math.min(sel.r, sel.r2) && +td.dataset.r <= Math.max(sel.r, sel.r2) && +td.dataset.c >= Math.min(sel.c, sel.c2) && +td.dataset.c <= Math.max(sel.c, sel.c2))) { const r = +td.dataset.r, c = +td.dataset.c; sel = { r, c, r2: r, c2: c }; paintSel(); }
354
+ const { r1, r2, c1, c2 } = range();
355
+ const op = (fn) => () => { snapshot(); fn(); changed(); };
356
+ window.SagaViewers.contextMenu(ev, [
357
+ { label: "Inserir linha acima", ic: "arrow-up", fn: op(() => data.splice(r1, 0, Array(width()).fill(""))) },
358
+ { label: "Inserir linha abaixo", ic: "arrow-down", fn: op(() => data.splice(r2 + 1, 0, Array(width()).fill(""))) },
359
+ { label: "Inserir coluna à esquerda", ic: "arrow-left", fn: op(() => data.forEach((r) => r.splice(c1, 0, ""))) },
360
+ { label: "Inserir coluna à direita", ic: "arrow-right", fn: op(() => data.forEach((r) => r.splice(c2 + 1, 0, ""))) },
361
+ { sep: true },
362
+ { label: r2 > r1 ? `Excluir ${r2 - r1 + 1} linhas` : "Excluir linha", ic: "trash-2", danger: true, fn: op(() => { data.splice(r1, r2 - r1 + 1); if (!data.length) data.push([""]); sel = { r: Math.min(r1, data.length - 1), c: sel.c, r2: Math.min(r1, data.length - 1), c2: sel.c }; }) },
363
+ { label: c2 > c1 ? `Excluir ${c2 - c1 + 1} colunas` : "Excluir coluna", ic: "trash-2", danger: true, fn: op(() => { data.forEach((r) => r.splice(c1, c2 - c1 + 1)); sel = { r: sel.r, c: Math.max(0, c1 - 1), r2: sel.r, c2: Math.max(0, c1 - 1) }; }) },
364
+ ]);
365
+ });
366
+ render();
367
+ if (data.length > maxRender) host.insertAdjacentHTML("beforeend", `<div class="sh-more">mostrando ${maxRender} de ${data.length} linhas</div>`);
368
+ return { get rows() { return data; }, focus: () => wrap.focus(), select: (r, c) => { sel = { r, c, r2: r, c2: c }; paintSel(); } };
369
+ }
370
+
371
+ window.SagaViewers = { langOf, highlight, codeEditor, pdfView, docxView, sheetGrid, colName, contextMenu: null };
372
+ })();