@fraziym/axoniz 0.1.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.
- package/LICENSE +21 -0
- package/README.md +76 -0
- package/dist/agents/definition.d.ts +15 -0
- package/dist/agents/definition.d.ts.map +1 -0
- package/dist/agents/definition.js +41 -0
- package/dist/agents/definition.js.map +1 -0
- package/dist/agents/index.d.ts +12 -0
- package/dist/agents/index.d.ts.map +1 -0
- package/dist/agents/index.js +11 -0
- package/dist/agents/index.js.map +1 -0
- package/dist/agents/registry.d.ts +17 -0
- package/dist/agents/registry.d.ts.map +1 -0
- package/dist/agents/registry.js +23 -0
- package/dist/agents/registry.js.map +1 -0
- package/dist/agents/specialized.d.ts +31 -0
- package/dist/agents/specialized.d.ts.map +1 -0
- package/dist/agents/specialized.js +75 -0
- package/dist/agents/specialized.js.map +1 -0
- package/dist/awareness/index.d.ts +14 -0
- package/dist/awareness/index.d.ts.map +1 -0
- package/dist/awareness/index.js +22 -0
- package/dist/awareness/index.js.map +1 -0
- package/dist/awareness/service.d.ts +180 -0
- package/dist/awareness/service.d.ts.map +1 -0
- package/dist/awareness/service.js +789 -0
- package/dist/awareness/service.js.map +1 -0
- package/dist/cli/entry.d.ts +13 -0
- package/dist/cli/entry.d.ts.map +1 -0
- package/dist/cli/entry.js +35 -0
- package/dist/cli/entry.js.map +1 -0
- package/dist/comms/telegram.d.ts +41 -0
- package/dist/comms/telegram.d.ts.map +1 -0
- package/dist/comms/telegram.js +332 -0
- package/dist/comms/telegram.js.map +1 -0
- package/dist/core/agent.d.ts +252 -0
- package/dist/core/agent.d.ts.map +1 -0
- package/dist/core/agent.js +1399 -0
- package/dist/core/agent.js.map +1 -0
- package/dist/core/auth.d.ts +23 -0
- package/dist/core/auth.d.ts.map +1 -0
- package/dist/core/auth.js +113 -0
- package/dist/core/auth.js.map +1 -0
- package/dist/core/authority.d.ts +118 -0
- package/dist/core/authority.d.ts.map +1 -0
- package/dist/core/authority.js +402 -0
- package/dist/core/authority.js.map +1 -0
- package/dist/core/backend/async_queue.d.ts +17 -0
- package/dist/core/backend/async_queue.d.ts.map +1 -0
- package/dist/core/backend/async_queue.js +66 -0
- package/dist/core/backend/async_queue.js.map +1 -0
- package/dist/core/backend/index.d.ts +24 -0
- package/dist/core/backend/index.d.ts.map +1 -0
- package/dist/core/backend/index.js +128 -0
- package/dist/core/backend/index.js.map +1 -0
- package/dist/core/backend/llama_server.d.ts +39 -0
- package/dist/core/backend/llama_server.d.ts.map +1 -0
- package/dist/core/backend/llama_server.js +182 -0
- package/dist/core/backend/llama_server.js.map +1 -0
- package/dist/core/backend/llamacpp.d.ts +40 -0
- package/dist/core/backend/llamacpp.d.ts.map +1 -0
- package/dist/core/backend/llamacpp.js +200 -0
- package/dist/core/backend/llamacpp.js.map +1 -0
- package/dist/core/backend/lmstudio.d.ts +53 -0
- package/dist/core/backend/lmstudio.d.ts.map +1 -0
- package/dist/core/backend/lmstudio.js +274 -0
- package/dist/core/backend/lmstudio.js.map +1 -0
- package/dist/core/backend/ollama.d.ts +25 -0
- package/dist/core/backend/ollama.d.ts.map +1 -0
- package/dist/core/backend/ollama.js +86 -0
- package/dist/core/backend/ollama.js.map +1 -0
- package/dist/core/backend/openai.d.ts +27 -0
- package/dist/core/backend/openai.d.ts.map +1 -0
- package/dist/core/backend/openai.js +84 -0
- package/dist/core/backend/openai.js.map +1 -0
- package/dist/core/backend/types.d.ts +73 -0
- package/dist/core/backend/types.d.ts.map +1 -0
- package/dist/core/backend/types.js +137 -0
- package/dist/core/backend/types.js.map +1 -0
- package/dist/core/chat_store.d.ts +77 -0
- package/dist/core/chat_store.d.ts.map +1 -0
- package/dist/core/chat_store.js +332 -0
- package/dist/core/chat_store.js.map +1 -0
- package/dist/core/cli.d.ts +82 -0
- package/dist/core/cli.d.ts.map +1 -0
- package/dist/core/cli.js +602 -0
- package/dist/core/cli.js.map +1 -0
- package/dist/core/config.d.ts +127 -0
- package/dist/core/config.d.ts.map +1 -0
- package/dist/core/config.js +295 -0
- package/dist/core/config.js.map +1 -0
- package/dist/core/debug.d.ts +8 -0
- package/dist/core/debug.d.ts.map +1 -0
- package/dist/core/debug.js +8 -0
- package/dist/core/debug.js.map +1 -0
- package/dist/core/downloader.d.ts +31 -0
- package/dist/core/downloader.d.ts.map +1 -0
- package/dist/core/downloader.js +180 -0
- package/dist/core/downloader.js.map +1 -0
- package/dist/core/errors.d.ts +80 -0
- package/dist/core/errors.d.ts.map +1 -0
- package/dist/core/errors.js +134 -0
- package/dist/core/errors.js.map +1 -0
- package/dist/core/extras.d.ts +160 -0
- package/dist/core/extras.d.ts.map +1 -0
- package/dist/core/extras.js +553 -0
- package/dist/core/extras.js.map +1 -0
- package/dist/core/health.d.ts +27 -0
- package/dist/core/health.d.ts.map +1 -0
- package/dist/core/health.js +96 -0
- package/dist/core/health.js.map +1 -0
- package/dist/core/history.d.ts +50 -0
- package/dist/core/history.d.ts.map +1 -0
- package/dist/core/history.js +276 -0
- package/dist/core/history.js.map +1 -0
- package/dist/core/index.d.ts +6 -0
- package/dist/core/index.d.ts.map +1 -0
- package/dist/core/index.js +6 -0
- package/dist/core/index.js.map +1 -0
- package/dist/core/intelligence/ast_index.d.ts +255 -0
- package/dist/core/intelligence/ast_index.d.ts.map +1 -0
- package/dist/core/intelligence/ast_index.js +1369 -0
- package/dist/core/intelligence/ast_index.js.map +1 -0
- package/dist/core/intelligence/confidence.d.ts +113 -0
- package/dist/core/intelligence/confidence.d.ts.map +1 -0
- package/dist/core/intelligence/confidence.js +298 -0
- package/dist/core/intelligence/confidence.js.map +1 -0
- package/dist/core/intelligence/context_compressor.d.ts +80 -0
- package/dist/core/intelligence/context_compressor.d.ts.map +1 -0
- package/dist/core/intelligence/context_compressor.js +245 -0
- package/dist/core/intelligence/context_compressor.js.map +1 -0
- package/dist/core/intelligence/daemon.d.ts +247 -0
- package/dist/core/intelligence/daemon.d.ts.map +1 -0
- package/dist/core/intelligence/daemon.js +842 -0
- package/dist/core/intelligence/daemon.js.map +1 -0
- package/dist/core/intelligence/index.d.ts +60 -0
- package/dist/core/intelligence/index.d.ts.map +1 -0
- package/dist/core/intelligence/index.js +101 -0
- package/dist/core/intelligence/index.js.map +1 -0
- package/dist/core/intelligence/predictor.d.ts +246 -0
- package/dist/core/intelligence/predictor.d.ts.map +1 -0
- package/dist/core/intelligence/predictor.js +590 -0
- package/dist/core/intelligence/predictor.js.map +1 -0
- package/dist/core/intelligence/reflex.d.ts +84 -0
- package/dist/core/intelligence/reflex.d.ts.map +1 -0
- package/dist/core/intelligence/reflex.js +344 -0
- package/dist/core/intelligence/reflex.js.map +1 -0
- package/dist/core/intelligence/self_correction.d.ts +121 -0
- package/dist/core/intelligence/self_correction.d.ts.map +1 -0
- package/dist/core/intelligence/self_correction.js +327 -0
- package/dist/core/intelligence/self_correction.js.map +1 -0
- package/dist/core/intelligence/skill_distiller.d.ts +100 -0
- package/dist/core/intelligence/skill_distiller.d.ts.map +1 -0
- package/dist/core/intelligence/skill_distiller.js +246 -0
- package/dist/core/intelligence/skill_distiller.js.map +1 -0
- package/dist/core/intelligence/swarm.d.ts +330 -0
- package/dist/core/intelligence/swarm.d.ts.map +1 -0
- package/dist/core/intelligence/swarm.js +1064 -0
- package/dist/core/intelligence/swarm.js.map +1 -0
- package/dist/core/intelligence/trajectory.d.ts +107 -0
- package/dist/core/intelligence/trajectory.d.ts.map +1 -0
- package/dist/core/intelligence/trajectory.js +330 -0
- package/dist/core/intelligence/trajectory.js.map +1 -0
- package/dist/core/logger.d.ts +111 -0
- package/dist/core/logger.d.ts.map +1 -0
- package/dist/core/logger.js +640 -0
- package/dist/core/logger.js.map +1 -0
- package/dist/core/loop.d.ts +123 -0
- package/dist/core/loop.d.ts.map +1 -0
- package/dist/core/loop.js +423 -0
- package/dist/core/loop.js.map +1 -0
- package/dist/core/memory.d.ts +81 -0
- package/dist/core/memory.d.ts.map +1 -0
- package/dist/core/memory.js +328 -0
- package/dist/core/memory.js.map +1 -0
- package/dist/core/metrics.d.ts +29 -0
- package/dist/core/metrics.d.ts.map +1 -0
- package/dist/core/metrics.js +109 -0
- package/dist/core/metrics.js.map +1 -0
- package/dist/core/models.d.ts +51 -0
- package/dist/core/models.d.ts.map +1 -0
- package/dist/core/models.js +146 -0
- package/dist/core/models.js.map +1 -0
- package/dist/core/optimizer.d.ts +34 -0
- package/dist/core/optimizer.d.ts.map +1 -0
- package/dist/core/optimizer.js +131 -0
- package/dist/core/optimizer.js.map +1 -0
- package/dist/core/persona.d.ts +35 -0
- package/dist/core/persona.d.ts.map +1 -0
- package/dist/core/persona.js +126 -0
- package/dist/core/persona.js.map +1 -0
- package/dist/core/rate_limit.d.ts +23 -0
- package/dist/core/rate_limit.d.ts.map +1 -0
- package/dist/core/rate_limit.js +62 -0
- package/dist/core/rate_limit.js.map +1 -0
- package/dist/core/runner.d.ts +63 -0
- package/dist/core/runner.d.ts.map +1 -0
- package/dist/core/runner.js +671 -0
- package/dist/core/runner.js.map +1 -0
- package/dist/core/stream_parser.d.ts +43 -0
- package/dist/core/stream_parser.d.ts.map +1 -0
- package/dist/core/stream_parser.js +140 -0
- package/dist/core/stream_parser.js.map +1 -0
- package/dist/core/tool_schemas.d.ts +26 -0
- package/dist/core/tool_schemas.d.ts.map +1 -0
- package/dist/core/tool_schemas.js +124 -0
- package/dist/core/tool_schemas.js.map +1 -0
- package/dist/core/which.d.ts +2 -0
- package/dist/core/which.d.ts.map +1 -0
- package/dist/core/which.js +35 -0
- package/dist/core/which.js.map +1 -0
- package/dist/goals/index.d.ts +9 -0
- package/dist/goals/index.d.ts.map +1 -0
- package/dist/goals/index.js +17 -0
- package/dist/goals/index.js.map +1 -0
- package/dist/goals/service.d.ts +115 -0
- package/dist/goals/service.d.ts.map +1 -0
- package/dist/goals/service.js +415 -0
- package/dist/goals/service.js.map +1 -0
- package/dist/goals/types.d.ts +47 -0
- package/dist/goals/types.d.ts.map +1 -0
- package/dist/goals/types.js +66 -0
- package/dist/goals/types.js.map +1 -0
- package/dist/index.d.ts +22 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +22 -0
- package/dist/index.js.map +1 -0
- package/dist/integrations/autonomous_startup.d.ts +51 -0
- package/dist/integrations/autonomous_startup.d.ts.map +1 -0
- package/dist/integrations/autonomous_startup.js +419 -0
- package/dist/integrations/autonomous_startup.js.map +1 -0
- package/dist/integrations/goose.d.ts +105 -0
- package/dist/integrations/goose.d.ts.map +1 -0
- package/dist/integrations/goose.js +408 -0
- package/dist/integrations/goose.js.map +1 -0
- package/dist/integrations/index.d.ts +21 -0
- package/dist/integrations/index.d.ts.map +1 -0
- package/dist/integrations/index.js +17 -0
- package/dist/integrations/index.js.map +1 -0
- package/dist/integrations/mcp.d.ts +73 -0
- package/dist/integrations/mcp.d.ts.map +1 -0
- package/dist/integrations/mcp.js +307 -0
- package/dist/integrations/mcp.js.map +1 -0
- package/dist/integrations/mempalace.d.ts +18 -0
- package/dist/integrations/mempalace.d.ts.map +1 -0
- package/dist/integrations/mempalace.js +25 -0
- package/dist/integrations/mempalace.js.map +1 -0
- package/dist/integrations/multi_agent.d.ts +82 -0
- package/dist/integrations/multi_agent.d.ts.map +1 -0
- package/dist/integrations/multi_agent.js +280 -0
- package/dist/integrations/multi_agent.js.map +1 -0
- package/dist/integrations/unified_memory.d.ts +415 -0
- package/dist/integrations/unified_memory.d.ts.map +1 -0
- package/dist/integrations/unified_memory.js +1489 -0
- package/dist/integrations/unified_memory.js.map +1 -0
- package/dist/roles/beru.yaml +48 -0
- package/dist/sidecar/client.d.ts +63 -0
- package/dist/sidecar/client.d.ts.map +1 -0
- package/dist/sidecar/client.js +222 -0
- package/dist/sidecar/client.js.map +1 -0
- package/dist/sidecar/index.d.ts +7 -0
- package/dist/sidecar/index.d.ts.map +1 -0
- package/dist/sidecar/index.js +6 -0
- package/dist/sidecar/index.js.map +1 -0
- package/dist/startup.d.ts +22 -0
- package/dist/startup.d.ts.map +1 -0
- package/dist/startup.js +194 -0
- package/dist/startup.js.map +1 -0
- package/dist/tools/_internal.d.ts +90 -0
- package/dist/tools/_internal.d.ts.map +1 -0
- package/dist/tools/_internal.js +375 -0
- package/dist/tools/_internal.js.map +1 -0
- package/dist/tools/_smoke.d.ts +2 -0
- package/dist/tools/_smoke.d.ts.map +1 -0
- package/dist/tools/_smoke.js +203 -0
- package/dist/tools/_smoke.js.map +1 -0
- package/dist/tools/axodex_tools.d.ts +51 -0
- package/dist/tools/axodex_tools.d.ts.map +1 -0
- package/dist/tools/axodex_tools.js +181 -0
- package/dist/tools/axodex_tools.js.map +1 -0
- package/dist/tools/code_tools.d.ts +33 -0
- package/dist/tools/code_tools.d.ts.map +1 -0
- package/dist/tools/code_tools.js +191 -0
- package/dist/tools/code_tools.js.map +1 -0
- package/dist/tools/computer_tools.d.ts +59 -0
- package/dist/tools/computer_tools.d.ts.map +1 -0
- package/dist/tools/computer_tools.js +348 -0
- package/dist/tools/computer_tools.js.map +1 -0
- package/dist/tools/file_tools.d.ts +51 -0
- package/dist/tools/file_tools.d.ts.map +1 -0
- package/dist/tools/file_tools.js +424 -0
- package/dist/tools/file_tools.js.map +1 -0
- package/dist/tools/index.d.ts +13 -0
- package/dist/tools/index.d.ts.map +1 -0
- package/dist/tools/index.js +13 -0
- package/dist/tools/index.js.map +1 -0
- package/dist/tools/shell_tools.d.ts +39 -0
- package/dist/tools/shell_tools.d.ts.map +1 -0
- package/dist/tools/shell_tools.js +163 -0
- package/dist/tools/shell_tools.js.map +1 -0
- package/dist/tools/web_tools.d.ts +31 -0
- package/dist/tools/web_tools.d.ts.map +1 -0
- package/dist/tools/web_tools.js +117 -0
- package/dist/tools/web_tools.js.map +1 -0
- package/dist/voice/index.d.ts +41 -0
- package/dist/voice/index.d.ts.map +1 -0
- package/dist/voice/index.js +58 -0
- package/dist/voice/index.js.map +1 -0
- package/dist/voice/light_daemon.d.ts +197 -0
- package/dist/voice/light_daemon.d.ts.map +1 -0
- package/dist/voice/light_daemon.js +746 -0
- package/dist/voice/light_daemon.js.map +1 -0
- package/dist/voice/setup.d.ts +63 -0
- package/dist/voice/setup.d.ts.map +1 -0
- package/dist/voice/setup.js +443 -0
- package/dist/voice/setup.js.map +1 -0
- package/dist/voice/stt.d.ts +148 -0
- package/dist/voice/stt.d.ts.map +1 -0
- package/dist/voice/stt.js +361 -0
- package/dist/voice/stt.js.map +1 -0
- package/dist/voice/tts.d.ts +168 -0
- package/dist/voice/tts.d.ts.map +1 -0
- package/dist/voice/tts.js +698 -0
- package/dist/voice/tts.js.map +1 -0
- package/dist/voice/voice_loop.d.ts +101 -0
- package/dist/voice/voice_loop.d.ts.map +1 -0
- package/dist/voice/voice_loop.js +463 -0
- package/dist/voice/voice_loop.js.map +1 -0
- package/dist/voice/wake_word.d.ts +153 -0
- package/dist/voice/wake_word.d.ts.map +1 -0
- package/dist/voice/wake_word.js +458 -0
- package/dist/voice/wake_word.js.map +1 -0
- package/dist/voice/wav.d.ts +99 -0
- package/dist/voice/wav.d.ts.map +1 -0
- package/dist/voice/wav.js +306 -0
- package/dist/voice/wav.js.map +1 -0
- package/dist/web/broker.d.ts +33 -0
- package/dist/web/broker.d.ts.map +1 -0
- package/dist/web/broker.js +58 -0
- package/dist/web/broker.js.map +1 -0
- package/dist/web/open_browser.d.ts +2 -0
- package/dist/web/open_browser.d.ts.map +1 -0
- package/dist/web/open_browser.js +42 -0
- package/dist/web/open_browser.js.map +1 -0
- package/dist/web/server.d.ts +54 -0
- package/dist/web/server.d.ts.map +1 -0
- package/dist/web/server.js +831 -0
- package/dist/web/server.js.map +1 -0
- package/dist/web/static/app.js +4121 -0
- package/dist/web/static/index.html +2281 -0
- package/dist/web/static/js/MODULE_SUMMARY.md +124 -0
- package/dist/web/static/js/a11y.js +165 -0
- package/dist/web/static/js/admin.js +2145 -0
- package/dist/web/static/js/assistant.js +475 -0
- package/dist/web/static/js/calendar/reminders.js +114 -0
- package/dist/web/static/js/calendar/utils.js +166 -0
- package/dist/web/static/js/calendar.js +3348 -0
- package/dist/web/static/js/censor.js +356 -0
- package/dist/web/static/js/chat.js +4546 -0
- package/dist/web/static/js/chatRenderer.js +2294 -0
- package/dist/web/static/js/chatStream.js +276 -0
- package/dist/web/static/js/codeRunner.js +398 -0
- package/dist/web/static/js/color/hex.js +14 -0
- package/dist/web/static/js/colorPicker.js +453 -0
- package/dist/web/static/js/compare/icons.js +77 -0
- package/dist/web/static/js/compare/index.js +1482 -0
- package/dist/web/static/js/compare/models.js +104 -0
- package/dist/web/static/js/compare/panes.js +817 -0
- package/dist/web/static/js/compare/probe.js +78 -0
- package/dist/web/static/js/compare/scoreboard.js +223 -0
- package/dist/web/static/js/compare/selector.js +1335 -0
- package/dist/web/static/js/compare/state.js +58 -0
- package/dist/web/static/js/compare/stream.js +695 -0
- package/dist/web/static/js/compare/vote.js +254 -0
- package/dist/web/static/js/cookbook-diagnosis.js +694 -0
- package/dist/web/static/js/cookbook-hwfit.js +1888 -0
- package/dist/web/static/js/cookbook.js +2093 -0
- package/dist/web/static/js/cookbookDownload.js +633 -0
- package/dist/web/static/js/cookbookProgressSignal.js +29 -0
- package/dist/web/static/js/cookbookRunning.js +3506 -0
- package/dist/web/static/js/cookbookServe.js +2128 -0
- package/dist/web/static/js/document.js +9731 -0
- package/dist/web/static/js/documentLibrary.js +3376 -0
- package/dist/web/static/js/dragSort.js +265 -0
- package/dist/web/static/js/editor/ai-inpaint.js +374 -0
- package/dist/web/static/js/editor/ai-models.js +273 -0
- package/dist/web/static/js/editor/ai-rembg.js +230 -0
- package/dist/web/static/js/editor/ai-tool-runner.js +147 -0
- package/dist/web/static/js/editor/ai-tools-misc.js +216 -0
- package/dist/web/static/js/editor/build/controls.js +366 -0
- package/dist/web/static/js/editor/build/popups.js +112 -0
- package/dist/web/static/js/editor/build/right-panel.js +200 -0
- package/dist/web/static/js/editor/build/toolbar.js +73 -0
- package/dist/web/static/js/editor/build/topbar.js +131 -0
- package/dist/web/static/js/editor/build/transform-popup.js +109 -0
- package/dist/web/static/js/editor/canvas-coords.js +21 -0
- package/dist/web/static/js/editor/canvas-events.js +197 -0
- package/dist/web/static/js/editor/canvas-transforms.js +132 -0
- package/dist/web/static/js/editor/checkerboard.js +24 -0
- package/dist/web/static/js/editor/clipboard-and-drop.js +133 -0
- package/dist/web/static/js/editor/composite-helpers.js +83 -0
- package/dist/web/static/js/editor/filters/blur.js +118 -0
- package/dist/web/static/js/editor/filters/edge-feather.js +70 -0
- package/dist/web/static/js/editor/fx/adj-popup.js +677 -0
- package/dist/web/static/js/editor/fx/filter-string.js +38 -0
- package/dist/web/static/js/editor/fx/histogram.js +67 -0
- package/dist/web/static/js/editor/fx/pixel-pass.js +249 -0
- package/dist/web/static/js/editor/harmonize-masks.js +116 -0
- package/dist/web/static/js/editor/history-panel.js +176 -0
- package/dist/web/static/js/editor/keyboard-shortcuts.js +271 -0
- package/dist/web/static/js/editor/layer-helpers.js +131 -0
- package/dist/web/static/js/editor/layer-panel.js +600 -0
- package/dist/web/static/js/editor/mask-utils.js +91 -0
- package/dist/web/static/js/editor/shortcuts-popover.js +149 -0
- package/dist/web/static/js/editor/slider-ux.js +191 -0
- package/dist/web/static/js/editor/snap.js +107 -0
- package/dist/web/static/js/editor/state.js +257 -0
- package/dist/web/static/js/editor/stroke-pipeline.js +162 -0
- package/dist/web/static/js/editor/stroke-tool-sliders.js +64 -0
- package/dist/web/static/js/editor/tools/clone.js +81 -0
- package/dist/web/static/js/editor/tools/crop.js +137 -0
- package/dist/web/static/js/editor/tools/flood-fill.js +72 -0
- package/dist/web/static/js/editor/tools/lasso-mask.js +171 -0
- package/dist/web/static/js/editor/tools/lasso.js +65 -0
- package/dist/web/static/js/editor/tools/move.js +79 -0
- package/dist/web/static/js/editor/tools/stroke.js +123 -0
- package/dist/web/static/js/editor/tools/transform-drag.js +174 -0
- package/dist/web/static/js/editor/tools/transform-handles.js +271 -0
- package/dist/web/static/js/editor/tools/transform-session.js +381 -0
- package/dist/web/static/js/editor/tools/wand.js +46 -0
- package/dist/web/static/js/editor/wire-import.js +148 -0
- package/dist/web/static/js/editor/wire-inpaint-controls.js +164 -0
- package/dist/web/static/js/editor/wire-merge-buttons.js +103 -0
- package/dist/web/static/js/editor/wire-selection-controls.js +170 -0
- package/dist/web/static/js/editor/wire-topbar-menus.js +174 -0
- package/dist/web/static/js/editor/wire-topbar-overflow.js +49 -0
- package/dist/web/static/js/editor/wire-topbar.js +188 -0
- package/dist/web/static/js/emailInbox.js +1245 -0
- package/dist/web/static/js/emailLibrary/replyRecipients.js +27 -0
- package/dist/web/static/js/emailLibrary/signatureFold.js +339 -0
- package/dist/web/static/js/emailLibrary/state.js +34 -0
- package/dist/web/static/js/emailLibrary/utils.js +202 -0
- package/dist/web/static/js/emailLibrary.js +5217 -0
- package/dist/web/static/js/emojiPicker.js +311 -0
- package/dist/web/static/js/escMenuStack.js +102 -0
- package/dist/web/static/js/fileHandler.js +295 -0
- package/dist/web/static/js/gallery.js +2835 -0
- package/dist/web/static/js/galleryEditor.js +3798 -0
- package/dist/web/static/js/group.js +955 -0
- package/dist/web/static/js/init.js +405 -0
- package/dist/web/static/js/keyboard-shortcuts.js +292 -0
- package/dist/web/static/js/langIcons.js +187 -0
- package/dist/web/static/js/markdown/tableRow.js +19 -0
- package/dist/web/static/js/markdown.js +806 -0
- package/dist/web/static/js/memory.js +1418 -0
- package/dist/web/static/js/modalManager.js +1552 -0
- package/dist/web/static/js/modalSnap.js +782 -0
- package/dist/web/static/js/model/matchKey.js +19 -0
- package/dist/web/static/js/modelPicker.js +695 -0
- package/dist/web/static/js/modelSort.js +33 -0
- package/dist/web/static/js/models.js +642 -0
- package/dist/web/static/js/notes.js +5054 -0
- package/dist/web/static/js/package.json +1 -0
- package/dist/web/static/js/platform.js +47 -0
- package/dist/web/static/js/presets.js +1110 -0
- package/dist/web/static/js/providers.js +93 -0
- package/dist/web/static/js/rag.js +177 -0
- package/dist/web/static/js/research/jobs.js +335 -0
- package/dist/web/static/js/research/panel.js +1233 -0
- package/dist/web/static/js/researchSynapse.js +225 -0
- package/dist/web/static/js/search-chat.js +201 -0
- package/dist/web/static/js/search.js +52 -0
- package/dist/web/static/js/section-management.js +260 -0
- package/dist/web/static/js/sessions.js +3108 -0
- package/dist/web/static/js/settings.js +4991 -0
- package/dist/web/static/js/sidebar-layout.js +573 -0
- package/dist/web/static/js/signature.js +504 -0
- package/dist/web/static/js/skills.js +1908 -0
- package/dist/web/static/js/slashAutocomplete.js +267 -0
- package/dist/web/static/js/slashCommands.js +6099 -0
- package/dist/web/static/js/spinner.js +406 -0
- package/dist/web/static/js/storage.js +123 -0
- package/dist/web/static/js/tasks.js +2699 -0
- package/dist/web/static/js/theme.js +2086 -0
- package/dist/web/static/js/tileManager.js +386 -0
- package/dist/web/static/js/tourAutoplay.js +133 -0
- package/dist/web/static/js/tourHints.js +179 -0
- package/dist/web/static/js/tts-ai.js +521 -0
- package/dist/web/static/js/ui.js +1288 -0
- package/dist/web/static/js/util/ordinal.js +13 -0
- package/dist/web/static/js/voiceRecorder.js +283 -0
- package/dist/web/static/js/windowDrag.js +326 -0
- package/dist/web/static/js/windowResize.js +233 -0
- package/dist/web/static/landing.html +824 -0
- package/dist/web/static/lib/docx.umd.min.js +20116 -0
- package/dist/web/static/lib/highlight.min.js +1213 -0
- package/dist/web/static/lib/html2pdf.bundle.min.js +3 -0
- package/dist/web/static/lib/mammoth.browser.min.js +21 -0
- package/dist/web/static/lib/qrcode.min.js +8 -0
- package/dist/web/static/lib/xlsx.full.min.js +24 -0
- package/dist/web/static/login.html +582 -0
- package/dist/web/static/manifest.json +15 -0
- package/dist/web/static/style.css +35733 -0
- package/dist/web/static/sw.js +144 -0
- package/dist/workflows/engine.d.ts +162 -0
- package/dist/workflows/engine.d.ts.map +1 -0
- package/dist/workflows/engine.js +625 -0
- package/dist/workflows/engine.js.map +1 -0
- package/dist/workflows/index.d.ts +8 -0
- package/dist/workflows/index.d.ts.map +1 -0
- package/dist/workflows/index.js +14 -0
- package/dist/workflows/index.js.map +1 -0
- package/package.json +112 -0
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Static markup for misc floating popups that live above the canvas.
|
|
3
|
+
*
|
|
4
|
+
* All pure DOM. Caller wires every ID via document.getElementById /
|
|
5
|
+
* el.querySelector after appending.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
/** Keyboard-shortcuts popover. */
|
|
9
|
+
export function shortcutsPopupHTML() {
|
|
10
|
+
return `
|
|
11
|
+
<div id="ge-shortcuts-handle" style="display:flex;align-items:center;gap:6px;margin:-4px -6px 4px;padding:4px 6px;cursor:grab;user-select:none;touch-action:none;">
|
|
12
|
+
<span style="display:inline-flex;flex-direction:column;gap:2px;margin-right:2px;opacity:0.35;">
|
|
13
|
+
<span style="display:block;width:18px;height:2px;border-radius:1px;background:currentColor;"></span>
|
|
14
|
+
<span style="display:block;width:18px;height:2px;border-radius:1px;background:currentColor;"></span>
|
|
15
|
+
</span>
|
|
16
|
+
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="opacity:0.8"><rect x="2" y="6" width="20" height="12" rx="2"/><path d="M6 10h.01M10 10h.01M14 10h.01M18 10h.01M7 14h10"/></svg>
|
|
17
|
+
<strong style="font-size:12px;letter-spacing:0.3px;">Editor Shortcuts</strong>
|
|
18
|
+
<span style="flex:1"></span>
|
|
19
|
+
<button id="ge-shortcuts-close" class="ge-btn ge-btn-sm" style="padding:0 6px;height:20px;line-height:1;background:none;border:none;opacity:0.55;cursor:pointer;color:var(--fg);">✖</button>
|
|
20
|
+
</div>
|
|
21
|
+
<div class="ge-shortcuts-grid">
|
|
22
|
+
<div class="ge-shortcuts-col">
|
|
23
|
+
<h5>Tools</h5>
|
|
24
|
+
<div><kbd>V</kbd> Move</div>
|
|
25
|
+
<div><kbd>T</kbd> Transform</div>
|
|
26
|
+
<div><kbd>B</kbd> Brush</div>
|
|
27
|
+
<div><kbd>E</kbd> Eraser</div>
|
|
28
|
+
<div><kbd>K</kbd> Clone Stamp <span style="opacity:0.5">(Alt-click = set source)</span></div>
|
|
29
|
+
<div><kbd>L</kbd> Lasso</div>
|
|
30
|
+
<div><kbd>W</kbd> Wand</div>
|
|
31
|
+
<div><kbd>M</kbd> Inpaint</div>
|
|
32
|
+
<div><kbd>E</kbd> Eraser</div>
|
|
33
|
+
<div><kbd>C</kbd> Crop</div>
|
|
34
|
+
<div><kbd>S</kbd> Sharpen</div>
|
|
35
|
+
</div>
|
|
36
|
+
<div class="ge-shortcuts-col">
|
|
37
|
+
<h5>Edit</h5>
|
|
38
|
+
<div><kbd>Ctrl</kbd>+<kbd>Z</kbd> Undo</div>
|
|
39
|
+
<div><kbd>Ctrl</kbd>+<kbd>Shift</kbd>+<kbd>Z</kbd> Redo</div>
|
|
40
|
+
<div><kbd>Ctrl</kbd>+<kbd>S</kbd> Save</div>
|
|
41
|
+
<div><kbd>Ctrl</kbd>+<kbd>Shift</kbd>+<kbd>S</kbd> Save to Gallery</div>
|
|
42
|
+
<div><kbd>Ctrl</kbd>+<kbd>Alt</kbd>+<kbd>J</kbd> New Layer</div>
|
|
43
|
+
<div><kbd>Ctrl</kbd>+<kbd>Alt</kbd>+<kbd>T</kbd> Free Transform</div>
|
|
44
|
+
<div><kbd>Ctrl</kbd>+<kbd>Shift</kbd>+<kbd>T</kbd> Canvas size…</div>
|
|
45
|
+
</div>
|
|
46
|
+
<div class="ge-shortcuts-col">
|
|
47
|
+
<h5>Selection</h5>
|
|
48
|
+
<div><kbd>Ctrl</kbd>+<kbd>A</kbd> Select All</div>
|
|
49
|
+
<div><kbd>Ctrl</kbd>+<kbd>Shift</kbd>+<kbd>D</kbd> Deselect</div>
|
|
50
|
+
<div><kbd>Ctrl</kbd>+<kbd>C</kbd> Copy to layer</div>
|
|
51
|
+
<div><kbd>Ctrl</kbd>+<kbd>X</kbd> Cut lasso</div>
|
|
52
|
+
<div><kbd>Ctrl</kbd>+<kbd>D</kbd> Delete pixels</div>
|
|
53
|
+
<div><kbd>Esc</kbd> Cancel selection / crop</div>
|
|
54
|
+
</div>
|
|
55
|
+
<div class="ge-shortcuts-col">
|
|
56
|
+
<h5>Brush / Mask</h5>
|
|
57
|
+
<div><kbd>[</kbd> Brush size −</div>
|
|
58
|
+
<div><kbd>]</kbd> Brush size +</div>
|
|
59
|
+
<div>Drag tolerance slider → live wand retune</div>
|
|
60
|
+
</div>
|
|
61
|
+
</div>
|
|
62
|
+
<div style="margin-top:8px;font-size:10px;opacity:0.5;text-align:center;">Press <kbd>?</kbd> or click the keyboard icon to toggle.</div>
|
|
63
|
+
`;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* History panel — sidebar listing all undo entries.
|
|
69
|
+
* @param {string} historyIcon Inline SVG markup for the title icon.
|
|
70
|
+
*/
|
|
71
|
+
export function historyPanelHTML(historyIcon) {
|
|
72
|
+
return `
|
|
73
|
+
<div class="ge-history-head" data-history-drag>
|
|
74
|
+
<span class="ge-adj-icon">${historyIcon}</span>
|
|
75
|
+
<span class="ge-history-title">History</span>
|
|
76
|
+
<span class="ge-head-btns">
|
|
77
|
+
<button class="ge-adj-min" type="button" title="Minimise">−</button>
|
|
78
|
+
</span>
|
|
79
|
+
</div>
|
|
80
|
+
<div class="ge-history-list" id="ge-history-list"></div>
|
|
81
|
+
`;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* Empty-canvas size-prompt modal — body markup (caller controls show /
|
|
87
|
+
* hide and wires the Cancel / Create buttons).
|
|
88
|
+
*/
|
|
89
|
+
export function canvasSizePromptHTML() {
|
|
90
|
+
return `
|
|
91
|
+
<div class="modal-content ge-canvas-prompt">
|
|
92
|
+
<div class="modal-header"><h4 id="ge-canvas-prompt-title">New canvas</h4></div>
|
|
93
|
+
<div class="modal-body">
|
|
94
|
+
<div class="ge-canvas-prompt-row">
|
|
95
|
+
<label class="ge-canvas-prompt-field">
|
|
96
|
+
<span>Width</span>
|
|
97
|
+
<input type="text" id="ge-canvas-prompt-w" inputmode="numeric" value="1024">
|
|
98
|
+
</label>
|
|
99
|
+
<span class="ge-canvas-prompt-x">×</span>
|
|
100
|
+
<label class="ge-canvas-prompt-field">
|
|
101
|
+
<span>Height</span>
|
|
102
|
+
<input type="text" id="ge-canvas-prompt-h" inputmode="numeric" value="1024">
|
|
103
|
+
</label>
|
|
104
|
+
</div>
|
|
105
|
+
<p class="ge-canvas-prompt-hint">Pixels, or type a ratio like 3x5 / 16:9 in either field.</p>
|
|
106
|
+
</div>
|
|
107
|
+
<div class="modal-footer">
|
|
108
|
+
<button class="confirm-btn confirm-btn-secondary" id="ge-canvas-prompt-cancel">Cancel</button>
|
|
109
|
+
<button class="confirm-btn confirm-btn-primary" id="ge-canvas-prompt-ok">Create</button>
|
|
110
|
+
</div>
|
|
111
|
+
</div>`;
|
|
112
|
+
}
|
|
@@ -0,0 +1,200 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Build the right-hand panel (controls + layers) — DOM creation,
|
|
3
|
+
* controls innerHTML population, mobile bottom-sheet swipe behavior,
|
|
4
|
+
* controls-panel re-parenting on mobile, slider value-chip layout
|
|
5
|
+
* normalization, layer-panel header + mobile peek/expand swipe, and
|
|
6
|
+
* the panel-width drag-resize handle.
|
|
7
|
+
*
|
|
8
|
+
* Owns its own event listeners (touch swipe gestures, mouse resize
|
|
9
|
+
* drag). Returns the `rightPanel` element + the `panelResize` handle
|
|
10
|
+
* + the inner `controls` element so the caller can wire any post-
|
|
11
|
+
* mount tweaks. Reads state.container (for mobile re-parenting) and
|
|
12
|
+
* state.color / state.brushSize / state.wandTolerance (initial slider
|
|
13
|
+
* values).
|
|
14
|
+
*
|
|
15
|
+
* @param {{
|
|
16
|
+
* controlsHTML: (ctx: {color, brushSize, wandTolerance}) => string,
|
|
17
|
+
* layerPanelHTML: () => string,
|
|
18
|
+
* }} build
|
|
19
|
+
*
|
|
20
|
+
* @returns {{
|
|
21
|
+
* rightPanel: HTMLDivElement,
|
|
22
|
+
* controls: HTMLDivElement,
|
|
23
|
+
* layerPanel: HTMLDivElement,
|
|
24
|
+
* panelResize: HTMLDivElement,
|
|
25
|
+
* }}
|
|
26
|
+
*/
|
|
27
|
+
import { state } from '../state.js';
|
|
28
|
+
|
|
29
|
+
export function buildRightPanel({ controlsHTML, layerPanelHTML }) {
|
|
30
|
+
const rightPanel = document.createElement('div');
|
|
31
|
+
rightPanel.className = 'ge-right-panel';
|
|
32
|
+
|
|
33
|
+
// Controls section.
|
|
34
|
+
const controls = document.createElement('div');
|
|
35
|
+
controls.className = 'ge-controls';
|
|
36
|
+
// Swipe-down to dismiss on mobile. Tap the same tool again to bring
|
|
37
|
+
// the sheet back. Only the top ~40 px (grab handle area) initiates
|
|
38
|
+
// the gesture so taps on inputs/sliders inside the panel still work.
|
|
39
|
+
{
|
|
40
|
+
let sy = 0, dragging = false;
|
|
41
|
+
controls.addEventListener('touchstart', (e) => {
|
|
42
|
+
if (window.innerWidth > 700) return;
|
|
43
|
+
const rect = controls.getBoundingClientRect();
|
|
44
|
+
const t = e.touches[0];
|
|
45
|
+
// Only engage if touch starts in the top grab zone.
|
|
46
|
+
if (t.clientY - rect.top > 40) return;
|
|
47
|
+
sy = t.clientY;
|
|
48
|
+
dragging = true;
|
|
49
|
+
controls.style.transition = 'none';
|
|
50
|
+
}, { passive: true });
|
|
51
|
+
controls.addEventListener('touchmove', (e) => {
|
|
52
|
+
if (!dragging) return;
|
|
53
|
+
const dy = e.touches[0].clientY - sy;
|
|
54
|
+
if (dy > 0) controls.style.transform = `translateY(${dy}px)`;
|
|
55
|
+
}, { passive: true });
|
|
56
|
+
controls.addEventListener('touchend', (e) => {
|
|
57
|
+
if (!dragging) return;
|
|
58
|
+
dragging = false;
|
|
59
|
+
const dy = e.changedTouches[0].clientY - sy;
|
|
60
|
+
controls.style.transition = '';
|
|
61
|
+
controls.style.transform = '';
|
|
62
|
+
if (dy > 60) controls.classList.add('dismissed');
|
|
63
|
+
});
|
|
64
|
+
}
|
|
65
|
+
controls.innerHTML = controlsHTML({
|
|
66
|
+
color: state.color,
|
|
67
|
+
brushSize: state.brushSize,
|
|
68
|
+
wandTolerance: state.wandTolerance,
|
|
69
|
+
});
|
|
70
|
+
rightPanel.appendChild(controls);
|
|
71
|
+
// Mobile only (≤ 700 px — matches the .ge-editor-body column-stack
|
|
72
|
+
// breakpoint): the right panel becomes a transformed bottom-sheet,
|
|
73
|
+
// so any position:fixed descendant gets trapped by the transform
|
|
74
|
+
// and rides along with the panel. Re-parent the controls panel to
|
|
75
|
+
// the editor root so it can truly fix to the viewport bottom
|
|
76
|
+
// regardless of the layers-sheet state. On desktop, controls stay
|
|
77
|
+
// docked inside the right panel above the layers list.
|
|
78
|
+
if (window.innerWidth <= 700 && state.container) {
|
|
79
|
+
state.container.appendChild(controls);
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
// Move every slider-row's value chip out of its <label> and place
|
|
83
|
+
// it AFTER the slider, so the value sits on the right edge of the
|
|
84
|
+
// row instead of being smashed against the slider track on the left.
|
|
85
|
+
controls.querySelectorAll('.ge-eraser-row').forEach(row => {
|
|
86
|
+
const valueSpan = row.querySelector('label > span[id$="-label"]');
|
|
87
|
+
const slider = row.querySelector('input[type="range"]');
|
|
88
|
+
if (valueSpan && slider) {
|
|
89
|
+
valueSpan.classList.add('ge-slider-value');
|
|
90
|
+
slider.after(valueSpan);
|
|
91
|
+
}
|
|
92
|
+
});
|
|
93
|
+
|
|
94
|
+
// Layer panel.
|
|
95
|
+
const layerPanel = document.createElement('div');
|
|
96
|
+
layerPanel.className = 'ge-layers';
|
|
97
|
+
layerPanel.innerHTML = layerPanelHTML();
|
|
98
|
+
rightPanel.appendChild(layerPanel);
|
|
99
|
+
// Mobile: tap the header grab handle or swipe up/down to toggle
|
|
100
|
+
// the layers sheet between peek and expanded. The peek state
|
|
101
|
+
// always shows the active layer so users never lose access to it.
|
|
102
|
+
{
|
|
103
|
+
const header = layerPanel.querySelector('.ge-layers-header');
|
|
104
|
+
if (header) {
|
|
105
|
+
let sy = 0, sx = 0, dragging = false, didSwipe = false;
|
|
106
|
+
header.addEventListener('touchstart', (e) => {
|
|
107
|
+
if (window.innerWidth > 700) return;
|
|
108
|
+
if (e.target.closest('button')) return;
|
|
109
|
+
sy = e.touches[0].clientY;
|
|
110
|
+
sx = e.touches[0].clientX;
|
|
111
|
+
dragging = true;
|
|
112
|
+
didSwipe = false;
|
|
113
|
+
}, { passive: true });
|
|
114
|
+
header.addEventListener('touchend', (e) => {
|
|
115
|
+
if (!dragging) return;
|
|
116
|
+
dragging = false;
|
|
117
|
+
const dy = e.changedTouches[0].clientY - sy;
|
|
118
|
+
const dx = Math.abs(e.changedTouches[0].clientX - sx);
|
|
119
|
+
// Real swipe — three states cycle by direction:
|
|
120
|
+
// minimized → peek → expanded (swipe up)
|
|
121
|
+
// expanded → peek → minimized (swipe down)
|
|
122
|
+
if (Math.abs(dy) > 20 && Math.abs(dy) > dx) {
|
|
123
|
+
didSwipe = true;
|
|
124
|
+
const isExpanded = rightPanel.classList.contains('expanded');
|
|
125
|
+
const isMinimized = rightPanel.classList.contains('minimized');
|
|
126
|
+
if (dy < 0) {
|
|
127
|
+
if (isMinimized) {
|
|
128
|
+
rightPanel.classList.remove('minimized');
|
|
129
|
+
} else if (!isExpanded) {
|
|
130
|
+
rightPanel.classList.add('expanded');
|
|
131
|
+
}
|
|
132
|
+
} else {
|
|
133
|
+
if (isExpanded) {
|
|
134
|
+
rightPanel.classList.remove('expanded');
|
|
135
|
+
} else if (!isMinimized) {
|
|
136
|
+
rightPanel.classList.add('minimized');
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
e.preventDefault();
|
|
140
|
+
}
|
|
141
|
+
});
|
|
142
|
+
header.addEventListener('click', (e) => {
|
|
143
|
+
if (window.innerWidth > 700) return;
|
|
144
|
+
if (e.target.closest('button')) return;
|
|
145
|
+
if (didSwipe) { didSwipe = false; return; }
|
|
146
|
+
// Click cycles between peek and expanded; minimized comes
|
|
147
|
+
// back to peek (so a tap on the handle always reveals at
|
|
148
|
+
// least the active layer row).
|
|
149
|
+
if (rightPanel.classList.contains('minimized')) {
|
|
150
|
+
rightPanel.classList.remove('minimized');
|
|
151
|
+
} else {
|
|
152
|
+
rightPanel.classList.toggle('expanded');
|
|
153
|
+
}
|
|
154
|
+
});
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
// Horizontal drag handle on the LEFT edge of the right panel — drag
|
|
159
|
+
// left to widen, right to narrow. Persists chosen width in
|
|
160
|
+
// localStorage so it survives reopens. (Earlier version was a
|
|
161
|
+
// vertical-drag for height; horizontal feels more natural since
|
|
162
|
+
// cramped LAYER ROWS are about width, not height.)
|
|
163
|
+
const panelResize = document.createElement('div');
|
|
164
|
+
panelResize.className = 'ge-panel-resize';
|
|
165
|
+
panelResize.title = 'Drag to resize panel';
|
|
166
|
+
rightPanel.appendChild(panelResize);
|
|
167
|
+
try {
|
|
168
|
+
const savedW = parseInt(localStorage.getItem('ge-right-panel-width') || '', 10);
|
|
169
|
+
if (savedW && savedW > 160 && savedW < 800) rightPanel.style.flex = `0 0 ${savedW}px`;
|
|
170
|
+
} catch {}
|
|
171
|
+
let panelResizing = false;
|
|
172
|
+
let panelStartX = 0;
|
|
173
|
+
let panelStartW = 0;
|
|
174
|
+
panelResize.addEventListener('mousedown', (e) => {
|
|
175
|
+
panelResizing = true;
|
|
176
|
+
panelStartX = e.clientX;
|
|
177
|
+
panelStartW = rightPanel.getBoundingClientRect().width;
|
|
178
|
+
e.preventDefault();
|
|
179
|
+
document.body.style.cursor = 'ew-resize';
|
|
180
|
+
});
|
|
181
|
+
document.addEventListener('mousemove', (e) => {
|
|
182
|
+
if (!panelResizing) return;
|
|
183
|
+
// Dragging left → wider panel (the panel sits on the right of
|
|
184
|
+
// the editor, so a leftward drag pulls its left edge left).
|
|
185
|
+
const delta = panelStartX - e.clientX;
|
|
186
|
+
const next = Math.max(160, Math.min(window.innerWidth - 200, panelStartW + delta));
|
|
187
|
+
rightPanel.style.flex = `0 0 ${next}px`;
|
|
188
|
+
});
|
|
189
|
+
document.addEventListener('mouseup', () => {
|
|
190
|
+
if (!panelResizing) return;
|
|
191
|
+
panelResizing = false;
|
|
192
|
+
document.body.style.cursor = '';
|
|
193
|
+
try {
|
|
194
|
+
const w = Math.round(rightPanel.getBoundingClientRect().width);
|
|
195
|
+
localStorage.setItem('ge-right-panel-width', String(w));
|
|
196
|
+
} catch {}
|
|
197
|
+
});
|
|
198
|
+
|
|
199
|
+
return { rightPanel, controls, layerPanel, panelResize };
|
|
200
|
+
}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Build the editor's left-side tool palette.
|
|
3
|
+
*
|
|
4
|
+
* Pure DOM construction — no module state. The big tool-switch logic
|
|
5
|
+
* (cursor swap, control-section toggle, transform entry, inpaint
|
|
6
|
+
* mask plumbing, etc.) stays in the caller and arrives here as the
|
|
7
|
+
* `onSelectTool` callback.
|
|
8
|
+
*
|
|
9
|
+
* @param {{
|
|
10
|
+
* currentTool: string,
|
|
11
|
+
* onSelectTool: (toolId: string, btn: HTMLButtonElement, toolbar: HTMLDivElement) => void,
|
|
12
|
+
* onClearSelection: (which: 'lasso'|'wand') => void,
|
|
13
|
+
* }} ctx
|
|
14
|
+
* @returns {{ toolbar: HTMLDivElement, toolKeyMap: Record<string,string> }}
|
|
15
|
+
*/
|
|
16
|
+
export function buildToolbar({ currentTool, onSelectTool, onClearSelection }) {
|
|
17
|
+
const toolbar = document.createElement('div');
|
|
18
|
+
toolbar.className = 'ge-toolbar';
|
|
19
|
+
const tools = [
|
|
20
|
+
{ id: 'move', label: 'Move', icon: '✥', key: 'V' },
|
|
21
|
+
{ id: 'crop', label: 'Crop', icon: '✂', key: 'C' },
|
|
22
|
+
{ id: 'transform', label: 'Transform', icon: '⤢', key: 'T' },
|
|
23
|
+
{ sep: true },
|
|
24
|
+
{ id: 'brush', label: 'Brush', icon: '<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M9.06 11.9l8.07-8.06a2.85 2.85 0 1 1 4.03 4.03l-8.06 8.08"/><path d="M7.07 14.94c-1.66 0-3 1.35-3 3.02 0 1.33-2.5 1.52-2 2.02 1.08 1.1 2.49 2.02 4 2.02 2.2 0 4-1.8 4-4.04a3.01 3.01 0 0 0-3-3.02z"/></svg>', key: 'B' },
|
|
25
|
+
{ id: 'eraser', label: 'Eraser', icon: '<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M19.4 14.6 14.6 19.4a2 2 0 0 1-2.83 0L4.6 12.23a2 2 0 0 1 0-2.83l7.17-7.17a2 2 0 0 1 2.83 0l4.8 4.8a2 2 0 0 1 0 2.83Z"/><line x1="22" y1="21" x2="7" y2="21"/><line x1="14" y1="3" x2="9" y2="8"/></svg>', key: 'E' },
|
|
26
|
+
{ sep: true },
|
|
27
|
+
{ id: 'clone', label: 'Clone', icon: '<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="9" r="3"/><path d="M9 12l-3 4h12l-3-4"/><path d="M4 20h16"/></svg>', key: 'K' },
|
|
28
|
+
{ id: 'lasso', label: 'Lasso', icon: '⟡', key: 'L' },
|
|
29
|
+
{ id: 'wand', label: 'Wand', icon: '<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M15 4V2"/><path d="M15 16v-2"/><path d="M8 9h2"/><path d="M20 9h2"/><path d="M17.8 11.8L19 13"/><path d="M15 9h0"/><path d="M17.8 6.2L19 5"/><path d="M3 21l9-9"/><path d="M12.2 6.2L11 5"/></svg>', key: 'W' },
|
|
30
|
+
{ sep: true },
|
|
31
|
+
{ id: 'inpaint', label: 'Inpaint', ai: true, icon: '<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M9.06 11.9l8.07-8.06a2.85 2.85 0 1 1 4.03 4.03l-8.06 8.08"/><path d="M7.07 14.94c-1.66 0-3 1.35-3 3.02 0 1.33-2.5 1.52-2 2.02 1.08 1.1 2.49 2.02 4 2.02 2.2 0 4-1.8 4-4.04a3.01 3.01 0 0 0-3-3.02z"/></svg>', key: 'M' },
|
|
32
|
+
{ id: 'rembg', ai: true, label: 'Bg Remove', icon: '✄' },
|
|
33
|
+
{ id: 'sharpen', ai: true, label: 'Sharpen', icon: '◈', key: 'S' },
|
|
34
|
+
];
|
|
35
|
+
const toolKeyMap = {};
|
|
36
|
+
for (const t of tools) {
|
|
37
|
+
if (t.sep) {
|
|
38
|
+
const sep = document.createElement('div');
|
|
39
|
+
sep.className = 'ge-tool-sep';
|
|
40
|
+
sep.textContent = t.label;
|
|
41
|
+
toolbar.appendChild(sep);
|
|
42
|
+
continue;
|
|
43
|
+
}
|
|
44
|
+
if (t.key) toolKeyMap[t.key.toLowerCase()] = t.id;
|
|
45
|
+
const btn = document.createElement('button');
|
|
46
|
+
btn.className = 'ge-tool-btn' + (t.id === currentTool ? ' active' : '');
|
|
47
|
+
btn.dataset.tool = t.id;
|
|
48
|
+
btn.title = t.label + (t.key ? ` (${t.key})` : '');
|
|
49
|
+
// Heavy 4-point AI star marker for AI-backed tools — sits just to
|
|
50
|
+
// the left of the icon so the user can spot AI vs local tools at a
|
|
51
|
+
// glance now that the "AI Tools" separator is gone.
|
|
52
|
+
const aiStar = t.ai ? '<span class="ge-tool-ai" title="AI">✦</span>' : '';
|
|
53
|
+
btn.classList.toggle('is-ai', !!t.ai);
|
|
54
|
+
// Selection-clear badge — rendered only for tools that can hold a
|
|
55
|
+
// selection (lasso, wand). Inpaint masks are first-class sub-layers
|
|
56
|
+
// now so they get their own delete-X in the layer panel.
|
|
57
|
+
const clearBadge = (t.id === 'lasso' || t.id === 'wand')
|
|
58
|
+
? '<span class="ge-tool-clear" title="Clear selection" data-clear-tool="' + t.id + '">' +
|
|
59
|
+
'<svg width="9" height="9" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="3" stroke-linecap="round"><line x1="6" y1="6" x2="18" y2="18"/><line x1="18" y1="6" x2="6" y2="18"/></svg>' +
|
|
60
|
+
'</span>'
|
|
61
|
+
: '';
|
|
62
|
+
btn.innerHTML = `${aiStar}<span class="ge-tool-icon"${t.small ? ' style="font-size:14px"' : ''}>${t.icon}</span><span class="ge-tool-label">${t.label}</span>${clearBadge}`;
|
|
63
|
+
// Clear-badge click stops propagation so the tool itself doesn't
|
|
64
|
+
// toggle; the actual clear is handled by the caller.
|
|
65
|
+
btn.querySelector('.ge-tool-clear')?.addEventListener('click', (ev) => {
|
|
66
|
+
ev.stopPropagation();
|
|
67
|
+
onClearSelection(ev.currentTarget.dataset.clearTool);
|
|
68
|
+
});
|
|
69
|
+
btn.addEventListener('click', () => onSelectTool(t.id, btn, toolbar));
|
|
70
|
+
toolbar.appendChild(btn);
|
|
71
|
+
}
|
|
72
|
+
return { toolbar, toolKeyMap };
|
|
73
|
+
}
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Build the editor's top bar (undo/redo/history, zoom group, Image
|
|
3
|
+
* menu, Filter menu, Selection-edge menu, Shortcuts, Import, Save).
|
|
4
|
+
*
|
|
5
|
+
* Pure DOM — no module state, no event listeners. All wiring is done
|
|
6
|
+
* by the caller via `document.getElementById(...)` against the IDs
|
|
7
|
+
* baked into the markup.
|
|
8
|
+
*
|
|
9
|
+
* @returns {HTMLDivElement}
|
|
10
|
+
*/
|
|
11
|
+
export function buildTopbar() {
|
|
12
|
+
const topBar = document.createElement('div');
|
|
13
|
+
topBar.className = 'ge-topbar';
|
|
14
|
+
topBar.innerHTML = `
|
|
15
|
+
<div class="ge-topbar-left">
|
|
16
|
+
<span class="ge-alpha-badge" title="This editor is in active development — expect rough edges">ALPHA</span>
|
|
17
|
+
<button class="ge-btn ge-btn-sm ge-stacked-btn" id="ge-undo" title="Undo">
|
|
18
|
+
<span class="ge-stacked-glyph">↩</span>
|
|
19
|
+
<span class="ge-stacked-label">UNDO</span>
|
|
20
|
+
</button>
|
|
21
|
+
<button class="ge-btn ge-btn-sm ge-stacked-btn" id="ge-redo" title="Redo">
|
|
22
|
+
<span class="ge-stacked-glyph">↪</span>
|
|
23
|
+
<span class="ge-stacked-label">REDO</span>
|
|
24
|
+
</button>
|
|
25
|
+
<button class="ge-btn ge-btn-sm ge-stacked-btn" id="ge-history-btn" title="History — click an entry to jump to that state" aria-label="History">
|
|
26
|
+
<span class="ge-stacked-glyph"><svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M1 4v6h6"/><path d="M3.51 15a9 9 0 1 0 2.13-9.36L1 10"/><polyline points="12 7 12 12 16 14"/></svg></span>
|
|
27
|
+
<span class="ge-stacked-label">HISTORY</span>
|
|
28
|
+
</button>
|
|
29
|
+
<span class="ge-topbar-sep"></span>
|
|
30
|
+
<button class="ge-btn ge-btn-sm" id="ge-zoom-out" title="Zoom out">−</button>
|
|
31
|
+
<span class="ge-zoom-stack">
|
|
32
|
+
<span class="ge-zoom-glyph">
|
|
33
|
+
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="11" cy="11" r="7"/><line x1="21" y1="21" x2="16.65" y2="16.65"/></svg>
|
|
34
|
+
</span>
|
|
35
|
+
<span class="ge-zoom-label">100%</span>
|
|
36
|
+
</span>
|
|
37
|
+
<button class="ge-btn ge-btn-sm" id="ge-zoom-in" title="Zoom in">+</button>
|
|
38
|
+
<span class="ge-topbar-sep"></span>
|
|
39
|
+
<button class="ge-btn ge-btn-sm ge-stacked-btn" id="ge-zoom-fit" title="Fit to view" aria-pressed="false">
|
|
40
|
+
<span class="ge-stacked-glyph"><svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="4 14 4 20 10 20"/><polyline points="20 10 20 4 14 4"/><line x1="14" y1="10" x2="21" y2="3"/><line x1="3" y1="21" x2="10" y2="14"/></svg></span>
|
|
41
|
+
<span class="ge-stacked-label">FIT</span>
|
|
42
|
+
</button>
|
|
43
|
+
<button class="ge-btn ge-btn-sm ge-stacked-btn" id="ge-zoom-100" title="Actual size" aria-pressed="false">
|
|
44
|
+
<span class="ge-stacked-glyph">1:1</span>
|
|
45
|
+
<span class="ge-stacked-label">SCALE</span>
|
|
46
|
+
</button>
|
|
47
|
+
<span class="ge-topbar-sep"></span>
|
|
48
|
+
</div>
|
|
49
|
+
<div class="ge-topbar-right">
|
|
50
|
+
<span class="ge-canvas-size" id="ge-canvas-size" title="Canvas size" hidden></span>
|
|
51
|
+
<div class="ge-image-wrap">
|
|
52
|
+
<button class="ge-btn ge-btn-sm" id="ge-image-menu-btn" title="Image actions" aria-haspopup="true">Image ▾</button>
|
|
53
|
+
<div class="ge-image-menu dropdown" id="ge-image-menu" hidden>
|
|
54
|
+
<button class="dropdown-item-compact" data-image-action="resize">
|
|
55
|
+
<span class="dropdown-icon">⤢</span>
|
|
56
|
+
<span>Canvas…</span>
|
|
57
|
+
</button>
|
|
58
|
+
<div class="ge-filter-submenu-label">Transform</div>
|
|
59
|
+
<button class="dropdown-item-compact" data-image-action="rotate-90">
|
|
60
|
+
<span class="dropdown-icon"><svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M21 12a9 9 0 1 1-3-6.7"/><polyline points="21 3 21 9 15 9"/></svg></span>
|
|
61
|
+
<span>Rotate 90° CW</span>
|
|
62
|
+
</button>
|
|
63
|
+
<button class="dropdown-item-compact" data-image-action="rotate-180">
|
|
64
|
+
<span class="dropdown-icon"><svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="1 4 1 10 7 10"/><path d="M3.51 15a9 9 0 1 0 2.13-9.36L1 10"/></svg></span>
|
|
65
|
+
<span>Rotate 180°</span>
|
|
66
|
+
</button>
|
|
67
|
+
<button class="dropdown-item-compact" data-image-action="flip-h">
|
|
68
|
+
<span class="dropdown-icon"><svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M21 7v10a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V7"/><line x1="12" y1="3" x2="12" y2="21"/><polyline points="7 11 4 7 7 3"/><polyline points="17 11 20 7 17 3"/></svg></span>
|
|
69
|
+
<span>Flip horizontal</span>
|
|
70
|
+
</button>
|
|
71
|
+
<button class="dropdown-item-compact" data-image-action="flip-v">
|
|
72
|
+
<span class="dropdown-icon"><svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M17 21H7a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h10"/><line x1="3" y1="12" x2="21" y2="12"/><polyline points="11 7 7 4 3 7"/><polyline points="11 17 7 20 3 17"/></svg></span>
|
|
73
|
+
<span>Flip vertical</span>
|
|
74
|
+
</button>
|
|
75
|
+
</div>
|
|
76
|
+
</div>
|
|
77
|
+
<div class="ge-filter-wrap">
|
|
78
|
+
<button class="ge-btn ge-btn-sm" id="ge-filter-menu-btn" title="Filters" aria-haspopup="true">Filter ▾</button>
|
|
79
|
+
<div class="ge-filter-menu dropdown" id="ge-filter-menu" hidden>
|
|
80
|
+
<div class="ge-filter-submenu-label">Blur</div>
|
|
81
|
+
<button class="dropdown-item-compact" data-filter-action="blur-gaussian">
|
|
82
|
+
<span class="dropdown-icon ge-blur-icon ge-blur-gaussian" aria-hidden="true"></span>
|
|
83
|
+
<span>Gaussian Blur…</span>
|
|
84
|
+
</button>
|
|
85
|
+
<button class="dropdown-item-compact" data-filter-action="blur-zoom">
|
|
86
|
+
<span class="dropdown-icon ge-blur-icon ge-blur-zoom" aria-hidden="true"></span>
|
|
87
|
+
<span>Zoom Blur…</span>
|
|
88
|
+
</button>
|
|
89
|
+
</div>
|
|
90
|
+
</div>
|
|
91
|
+
<span class="ge-topbar-sep"></span>
|
|
92
|
+
<button class="ge-btn ge-btn-sm" id="ge-shortcuts-btn" title="Keyboard shortcuts (?)" aria-label="Shortcuts">
|
|
93
|
+
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="position:relative;top:2px;"><rect x="2" y="6" width="20" height="12" rx="2"/><path d="M6 10h.01M10 10h.01M14 10h.01M18 10h.01M7 14h10"/></svg>
|
|
94
|
+
</button>
|
|
95
|
+
<button class="ge-btn ge-btn-sm" id="ge-import-topbar" title="Import image as layer">+ Import</button>
|
|
96
|
+
<div class="ge-save-wrap">
|
|
97
|
+
<button class="ge-btn ge-btn-primary" id="ge-save-menu-btn" title="Save options" style="display:inline-flex;align-items:center;gap:4px;">Save
|
|
98
|
+
<svg width="9" height="9" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round" style="opacity:0.7"><polyline points="6 9 12 15 18 9"/></svg>
|
|
99
|
+
</button>
|
|
100
|
+
<div class="ge-save-menu dropdown" id="ge-save-menu" hidden>
|
|
101
|
+
<div class="dropdown-section-label">Image</div>
|
|
102
|
+
<button class="dropdown-item-compact" id="ge-save" title="Overwrite the original image">
|
|
103
|
+
<span class="dropdown-icon"><svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M19 21H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h11l5 5v11a2 2 0 0 1-2 2z"/><polyline points="17 21 17 13 7 13 7 21"/><polyline points="7 3 7 8 15 8"/></svg></span>
|
|
104
|
+
<span>Save over original</span>
|
|
105
|
+
<span class="dropdown-shortcut">Ctrl+S</span>
|
|
106
|
+
</button>
|
|
107
|
+
<button class="dropdown-item-compact" id="ge-export-gallery" title="Save as a new image in the gallery">
|
|
108
|
+
<span class="dropdown-icon"><svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M19 21H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h11l5 5v11a2 2 0 0 1-2 2z"/><line x1="12" y1="11" x2="12" y2="17"/><line x1="9" y1="14" x2="15" y2="14"/></svg></span>
|
|
109
|
+
<span>Save as copy</span>
|
|
110
|
+
<span class="dropdown-shortcut">Ctrl+Shift+S</span>
|
|
111
|
+
</button>
|
|
112
|
+
<button class="dropdown-item-compact" id="ge-download" title="Download PNG to your computer">
|
|
113
|
+
<span class="dropdown-icon"><svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"/><polyline points="7 10 12 15 17 10"/><line x1="12" y1="15" x2="12" y2="3"/></svg></span>
|
|
114
|
+
<span>Download PNG</span>
|
|
115
|
+
</button>
|
|
116
|
+
<div class="dropdown-section-divider"></div>
|
|
117
|
+
<div class="dropdown-section-label">Project</div>
|
|
118
|
+
<button class="dropdown-item-compact" id="ge-save-project" title="Save layered project (.json) — keeps every layer editable for later">
|
|
119
|
+
<span class="dropdown-icon"><svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect x="3" y="3" width="13" height="13" rx="1"/><rect x="8" y="8" width="13" height="13" rx="1"/></svg></span>
|
|
120
|
+
<span>Save project (.json)</span>
|
|
121
|
+
</button>
|
|
122
|
+
<button class="dropdown-item-compact" id="ge-load-project" title="Open a previously-saved project file">
|
|
123
|
+
<span class="dropdown-icon"><svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M22 19a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h5l2 3h9a2 2 0 0 1 2 2z"/></svg></span>
|
|
124
|
+
<span>Load project…</span>
|
|
125
|
+
</button>
|
|
126
|
+
</div>
|
|
127
|
+
</div>
|
|
128
|
+
</div>
|
|
129
|
+
`;
|
|
130
|
+
return topBar;
|
|
131
|
+
}
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Static markup for the Transform popup that floats over the canvas
|
|
3
|
+
* when the user activates the Resize/Transform tool.
|
|
4
|
+
*
|
|
5
|
+
* Pure DOM — no module state, no event listeners. The caller wires all
|
|
6
|
+
* IDs via document.getElementById / pop.querySelector.
|
|
7
|
+
*
|
|
8
|
+
* @returns {string}
|
|
9
|
+
*/
|
|
10
|
+
export function transformPopupHTML() {
|
|
11
|
+
return `
|
|
12
|
+
<div class="ge-adj-head ge-transform-popup-head" data-transform-drag>
|
|
13
|
+
<span class="ge-adj-icon">
|
|
14
|
+
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="3 7 7 3 11 7"/><line x1="7" y1="3" x2="7" y2="21"/><polyline points="21 17 17 21 13 17"/><line x1="17" y1="21" x2="17" y2="3"/></svg>
|
|
15
|
+
</span>
|
|
16
|
+
<span class="ge-adj-title">Transform</span>
|
|
17
|
+
<button type="button" id="ge-transform-aspect" class="ge-transform-aspect-btn" title="Lock aspect ratio" aria-pressed="true">
|
|
18
|
+
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect x="3" y="11" width="18" height="11" rx="2"/><path d="M7 11V7a5 5 0 0 1 10 0v4"/></svg>
|
|
19
|
+
</button>
|
|
20
|
+
<span class="ge-head-btns">
|
|
21
|
+
<button class="ge-adj-min" type="button" title="Minimise" id="ge-transform-min">−</button>
|
|
22
|
+
<button class="ge-adj-close" type="button" title="Cancel" id="ge-transform-cancel">×</button>
|
|
23
|
+
</span>
|
|
24
|
+
</div>
|
|
25
|
+
<div class="ge-transform-popup-body">
|
|
26
|
+
<div class="ge-transform-field">
|
|
27
|
+
<label>W</label>
|
|
28
|
+
<input type="number" class="ge-transform-popup-input" id="ge-transform-w" step="1" />
|
|
29
|
+
<span class="ge-transform-spin" data-spin-for="ge-transform-w">
|
|
30
|
+
<button type="button" data-spin="down" tabindex="-1" aria-label="Decrease width">−</button>
|
|
31
|
+
<button type="button" data-spin="up" tabindex="-1" aria-label="Increase width">+</button>
|
|
32
|
+
</span>
|
|
33
|
+
</div>
|
|
34
|
+
<div class="ge-transform-field">
|
|
35
|
+
<label>H</label>
|
|
36
|
+
<input type="number" class="ge-transform-popup-input" id="ge-transform-h" step="1" />
|
|
37
|
+
<span class="ge-transform-spin" data-spin-for="ge-transform-h">
|
|
38
|
+
<button type="button" data-spin="down" tabindex="-1" aria-label="Decrease height">−</button>
|
|
39
|
+
<button type="button" data-spin="up" tabindex="-1" aria-label="Increase height">+</button>
|
|
40
|
+
</span>
|
|
41
|
+
</div>
|
|
42
|
+
<div class="ge-row-break"></div>
|
|
43
|
+
<div class="ge-transform-field">
|
|
44
|
+
<label>↻</label>
|
|
45
|
+
<input type="number" class="ge-transform-popup-input ge-transform-popup-input-rot" id="ge-transform-rot" step="1" value="0" />
|
|
46
|
+
<span class="ge-transform-spin" data-spin-for="ge-transform-rot">
|
|
47
|
+
<button type="button" data-spin="down" tabindex="-1" aria-label="Rotate -1°">−</button>
|
|
48
|
+
<button type="button" data-spin="up" tabindex="-1" aria-label="Rotate +1°">+</button>
|
|
49
|
+
</span>
|
|
50
|
+
</div>
|
|
51
|
+
<button type="button" class="ge-btn ge-btn-sm" id="ge-transform-cancel-btn">Cancel</button>
|
|
52
|
+
<button type="button" class="ge-btn ge-btn-sm ge-btn-primary" id="ge-transform-apply">Apply</button>
|
|
53
|
+
</div>
|
|
54
|
+
<p class="ge-transform-popup-hint">Type <strong>-</strong> before W / H to flip.</p>
|
|
55
|
+
`;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* Wire a `<span class="ge-transform-spin">…<button data-spin="up|down"/>…</span>`
|
|
61
|
+
* group with tap-to-tick + hold-to-repeat. After 1.5 s the repeat
|
|
62
|
+
* accelerates from 70ms→30ms intervals so users can rapidly scrub a
|
|
63
|
+
* numeric field without mashing the button.
|
|
64
|
+
*
|
|
65
|
+
* On each tick, the helper looks up the target `<input>` by the
|
|
66
|
+
* spin-group's `data-spin-for` attribute and dispatches an `input`
|
|
67
|
+
* event so the rest of the popup's wiring picks up the change.
|
|
68
|
+
*
|
|
69
|
+
* @param {HTMLElement} root Element that owns one or more spin groups
|
|
70
|
+
* (e.g. the transform popup).
|
|
71
|
+
*/
|
|
72
|
+
export function attachSpinRepeat(root) {
|
|
73
|
+
root.querySelectorAll('.ge-transform-spin button').forEach(btn => {
|
|
74
|
+
const tick = (shift) => {
|
|
75
|
+
const targetId = btn.parentElement?.dataset?.spinFor;
|
|
76
|
+
if (!targetId) return;
|
|
77
|
+
const input = root.querySelector('#' + CSS.escape(targetId));
|
|
78
|
+
if (!input || input.readOnly) return;
|
|
79
|
+
const step = shift ? 10 : 1;
|
|
80
|
+
const cur = parseInt(input.value, 10) || 0;
|
|
81
|
+
const next = btn.dataset.spin === 'up' ? cur + step : cur - step;
|
|
82
|
+
input.value = String(next);
|
|
83
|
+
input.dispatchEvent(new Event('input', { bubbles: true }));
|
|
84
|
+
};
|
|
85
|
+
let holdTimeout = null, repeatInterval = null, started = 0;
|
|
86
|
+
btn.addEventListener('pointerdown', (e) => {
|
|
87
|
+
e.preventDefault();
|
|
88
|
+
tick(e.shiftKey);
|
|
89
|
+
started = Date.now();
|
|
90
|
+
holdTimeout = setTimeout(() => {
|
|
91
|
+
repeatInterval = setInterval(() => {
|
|
92
|
+
tick(false);
|
|
93
|
+
if (Date.now() - started > 1500 && repeatInterval) {
|
|
94
|
+
clearInterval(repeatInterval);
|
|
95
|
+
repeatInterval = setInterval(() => tick(false), 30);
|
|
96
|
+
}
|
|
97
|
+
}, 70);
|
|
98
|
+
}, 350);
|
|
99
|
+
});
|
|
100
|
+
const endHold = () => {
|
|
101
|
+
if (holdTimeout) clearTimeout(holdTimeout);
|
|
102
|
+
if (repeatInterval) clearInterval(repeatInterval);
|
|
103
|
+
holdTimeout = null; repeatInterval = null;
|
|
104
|
+
};
|
|
105
|
+
btn.addEventListener('pointerup', endHold);
|
|
106
|
+
btn.addEventListener('pointerleave', endHold);
|
|
107
|
+
btn.addEventListener('pointercancel', endHold);
|
|
108
|
+
});
|
|
109
|
+
}
|