auricui-skill 0.0.0-stage → 0.1.2
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 +29 -2
- package/bin/install.mjs +66 -0
- package/package.json +29 -4
- package/skill/SKILL.md +64 -0
- package/skill/agents/openai.yaml +4 -0
- package/skill/assets/examples/ApprovalCard.tsx +8 -0
- package/skill/assets/examples/BasicApp.tsx +38 -0
- package/skill/assets/examples/BriefingCard.tsx +8 -0
- package/skill/assets/examples/ChatControls.tsx +49 -0
- package/skill/assets/examples/ChatPanel.tsx +73 -0
- package/skill/assets/examples/Checkbox.tsx +13 -0
- package/skill/assets/examples/Combobox.tsx +14 -0
- package/skill/assets/examples/Drawer.tsx +10 -0
- package/skill/assets/examples/MemoryCard.tsx +9 -0
- package/skill/assets/examples/MessageList.tsx +8 -0
- package/skill/assets/examples/Theme.tsx +14 -0
- package/skill/assets/examples/ToolCall.tsx +8 -0
- package/skill/assets/examples/Tree.tsx +15 -0
- package/skill/assets/examples/examples.css +11 -0
- package/skill/assets/library/auricui-0.1.0-preview.1.tgz +0 -0
- package/skill/assets/library/auricui-0.1.0-preview.3.tgz +0 -0
- package/skill/assets/library/auricui-0.1.0-preview.4.tgz +0 -0
- package/skill/assets/upstream/LICENSE +21 -0
- package/skill/assets/upstream/apps/desktop/chat/src/App.tsx +1099 -0
- package/skill/assets/upstream/apps/desktop/chat/src/app-bridge.ts +154 -0
- package/skill/assets/upstream/apps/desktop/chat/src/chat.css +1812 -0
- package/skill/assets/upstream/apps/desktop/chat/src/components/AddSkill.tsx +223 -0
- package/skill/assets/upstream/apps/desktop/chat/src/components/AgentActivityRow.tsx +716 -0
- package/skill/assets/upstream/apps/desktop/chat/src/components/AgentIcons.tsx +46 -0
- package/skill/assets/upstream/apps/desktop/chat/src/components/AttachmentCard.tsx +34 -0
- package/skill/assets/upstream/apps/desktop/chat/src/components/AttachmentPreview.tsx +331 -0
- package/skill/assets/upstream/apps/desktop/chat/src/components/BalanceNotice.tsx +22 -0
- package/skill/assets/upstream/apps/desktop/chat/src/components/BrandLogo.tsx +35 -0
- package/skill/assets/upstream/apps/desktop/chat/src/components/ComposerCard.tsx +182 -0
- package/skill/assets/upstream/apps/desktop/chat/src/components/ConversationSessionBar.tsx +292 -0
- package/skill/assets/upstream/apps/desktop/chat/src/components/CopyDiagnostics.tsx +24 -0
- package/skill/assets/upstream/apps/desktop/chat/src/components/Divider.tsx +47 -0
- package/skill/assets/upstream/apps/desktop/chat/src/components/FileChangesList.tsx +119 -0
- package/skill/assets/upstream/apps/desktop/chat/src/components/Markdown.tsx +198 -0
- package/skill/assets/upstream/apps/desktop/chat/src/components/ModelPopover.tsx +280 -0
- package/skill/assets/upstream/apps/desktop/chat/src/components/NoticeCard.tsx +87 -0
- package/skill/assets/upstream/apps/desktop/chat/src/components/Popover.tsx +195 -0
- package/skill/assets/upstream/apps/desktop/chat/src/components/PreviewFrame.tsx +129 -0
- package/skill/assets/upstream/apps/desktop/chat/src/components/ProjectConversation.tsx +852 -0
- package/skill/assets/upstream/apps/desktop/chat/src/components/ProjectStarters.tsx +118 -0
- package/skill/assets/upstream/apps/desktop/chat/src/components/Tooltip.tsx +191 -0
- package/skill/assets/upstream/apps/desktop/chat/src/components/TurnLog.tsx +583 -0
- package/skill/assets/upstream/apps/desktop/chat/src/components/TurnQuestionCard.tsx +133 -0
- package/skill/assets/upstream/apps/desktop/chat/src/components/dock-pane-bar.ts +14 -0
- package/skill/assets/upstream/apps/desktop/chat/src/components/project-version.ts +37 -0
- package/skill/assets/upstream/apps/desktop/chat/src/components/prompt-editor/MentionMenuPlugin.tsx +372 -0
- package/skill/assets/upstream/apps/desktop/chat/src/components/prompt-editor/PromptEditor.tsx +476 -0
- package/skill/assets/upstream/apps/desktop/chat/src/components/prompt-editor/PromptPill.tsx +399 -0
- package/skill/assets/upstream/apps/desktop/chat/src/components/prompt-editor/PromptReferenceNode.tsx +164 -0
- package/skill/assets/upstream/apps/desktop/chat/src/components/prompt-editor/index.ts +31 -0
- package/skill/assets/upstream/apps/desktop/chat/src/components/prompt-editor/mention-menu.ts +206 -0
- package/skill/assets/upstream/apps/desktop/chat/src/components/prompt-editor/prompt-text.ts +171 -0
- package/skill/assets/upstream/apps/desktop/chat/src/components/useStickToBottom.ts +320 -0
- package/skill/assets/upstream/apps/desktop/chat/src/components/useTicker.ts +55 -0
- package/skill/assets/upstream/apps/desktop/chat/src/i18n/index.ts +42 -0
- package/skill/assets/upstream/apps/desktop/chat/src/i18n/locales/en-US.ts +408 -0
- package/skill/assets/upstream/apps/desktop/chat/src/i18n/locales/es.ts +407 -0
- package/skill/assets/upstream/apps/desktop/chat/src/i18n/locales/ja.ts +407 -0
- package/skill/assets/upstream/apps/desktop/chat/src/i18n/locales/ko.ts +403 -0
- package/skill/assets/upstream/apps/desktop/chat/src/i18n/locales/words.ts +6 -0
- package/skill/assets/upstream/apps/desktop/chat/src/i18n/locales/zh-CN.ts +407 -0
- package/skill/assets/upstream/apps/desktop/chat/src/i18n/lookup.ts +12 -0
- package/skill/assets/upstream/apps/desktop/chat/src/lib/agent-activity-runs.ts +154 -0
- package/skill/assets/upstream/apps/desktop/chat/src/lib/agent-menu-rows.ts +41 -0
- package/skill/assets/upstream/apps/desktop/chat/src/lib/agent-refs.ts +105 -0
- package/skill/assets/upstream/apps/desktop/chat/src/lib/agent-transcript.ts +440 -0
- package/skill/assets/upstream/apps/desktop/chat/src/lib/asset-lists.ts +75 -0
- package/skill/assets/upstream/apps/desktop/chat/src/lib/attachment-place.ts +17 -0
- package/skill/assets/upstream/apps/desktop/chat/src/lib/balance.ts +16 -0
- package/skill/assets/upstream/apps/desktop/chat/src/lib/chat-layer.ts +10 -0
- package/skill/assets/upstream/apps/desktop/chat/src/lib/chat-menu.ts +18 -0
- package/skill/assets/upstream/apps/desktop/chat/src/lib/chat-store.ts +101 -0
- package/skill/assets/upstream/apps/desktop/chat/src/lib/composer-attachments.ts +189 -0
- package/skill/assets/upstream/apps/desktop/chat/src/lib/desktop-attachments.ts +178 -0
- package/skill/assets/upstream/apps/desktop/chat/src/lib/desktop-bridge.ts +291 -0
- package/skill/assets/upstream/apps/desktop/chat/src/lib/developer.ts +39 -0
- package/skill/assets/upstream/apps/desktop/chat/src/lib/esc-stop.ts +23 -0
- package/skill/assets/upstream/apps/desktop/chat/src/lib/file-changes.ts +32 -0
- package/skill/assets/upstream/apps/desktop/chat/src/lib/live-activity.ts +20 -0
- package/skill/assets/upstream/apps/desktop/chat/src/lib/local-agent-run.ts +1174 -0
- package/skill/assets/upstream/apps/desktop/chat/src/lib/local-sessions.ts +25 -0
- package/skill/assets/upstream/apps/desktop/chat/src/lib/model-calls.ts +87 -0
- package/skill/assets/upstream/apps/desktop/chat/src/lib/pretty-json.ts +12 -0
- package/skill/assets/upstream/apps/desktop/chat/src/lib/preview-top.ts +15 -0
- package/skill/assets/upstream/apps/desktop/chat/src/lib/project-resources.ts +66 -0
- package/skill/assets/upstream/apps/desktop/chat/src/lib/project-sessions.ts +66 -0
- package/skill/assets/upstream/apps/desktop/chat/src/lib/project-versions.ts +116 -0
- package/skill/assets/upstream/apps/desktop/chat/src/lib/ref-pictures.ts +119 -0
- package/skill/assets/upstream/apps/desktop/chat/src/lib/relative-time.ts +46 -0
- package/skill/assets/upstream/apps/desktop/chat/src/lib/skill-pages.ts +29 -0
- package/skill/assets/upstream/apps/desktop/chat/src/lib/step-file.ts +23 -0
- package/skill/assets/upstream/apps/desktop/chat/src/lib/structural-share.ts +52 -0
- package/skill/assets/upstream/apps/desktop/chat/src/lib/studio-film.ts +44 -0
- package/skill/assets/upstream/apps/desktop/chat/src/lib/studio-transfer.ts +40 -0
- package/skill/assets/upstream/apps/desktop/chat/src/lib/unprompted.ts +27 -0
- package/skill/assets/upstream/apps/desktop/chat/src/lib/upload-limits.ts +53 -0
- package/skill/assets/upstream/apps/desktop/chat/src/mount.tsx +19 -0
- package/skill/assets/upstream/apps/desktop/chat/src/state/local-agent-store.ts +296 -0
- package/skill/assets/upstream/apps/desktop/chat/src/studio-refs.ts +307 -0
- package/skill/assets/upstream/apps/desktop/package.json +51 -0
- package/skill/assets/upstream/apps/desktop/shell/bridge.ts +415 -0
- package/skill/assets/upstream/apps/desktop/shell/index.html +27 -0
- package/skill/assets/upstream/apps/desktop/shell/main.tsx +17 -0
- package/skill/assets/upstream/apps/desktop/shell/shell.css +17 -0
- package/skill/assets/upstream/apps/desktop/shell/vite.config.ts +65 -0
- package/skill/assets/upstream/apps/desktop/src/agent-definitions.mjs +31 -0
- package/skill/assets/upstream/packages/openfilm/LICENSE +21 -0
- package/skill/assets/upstream/packages/openfilm/package.json +88 -0
- package/skill/assets/upstream/packages/openfilm/src/film-doc.d.mts +125 -0
- package/skill/assets/upstream/packages/openfilm/src/film-doc.mjs +986 -0
- package/skill/assets/upstream/packages/openfilm/src/overrides.mjs +73 -0
- package/skill/assets/upstream/packages/openfilm/src/timeline.mjs +1280 -0
- package/skill/assets/upstream/packages/openfilm/studio/server/bridge.js +209 -0
- package/skill/assets/upstream/packages/openfilm/studio/server/film-subtitle.mjs +785 -0
- package/skill/assets/upstream/packages/openfilm/studio/server/ops.mjs +403 -0
- package/skill/assets/upstream/packages/openfilm/studio/server/stage.js +1649 -0
- package/skill/assets/upstream/packages/openfilm/studio/server/track-layout.mjs +43 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/App.tsx +156 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/api.ts +328 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/components/AudioMeters.tsx +188 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/components/BlockThumbs.tsx +84 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/components/BlockWaveform.tsx +201 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/components/BrandLoadingScreen.tsx +56 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/components/BrandLogo.tsx +25 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/components/Card.tsx +89 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/components/ColorPicker.tsx +204 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/components/ConfirmDialog.tsx +96 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/components/ContextMenu.tsx +422 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/components/DesktopDialog.tsx +271 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/components/ExamplesGallery.tsx +372 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/components/FilmFullscreenBar.tsx +147 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/components/FilmInspector.tsx +2310 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/components/FilmStageSelect.tsx +3296 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/components/FocusNav.tsx +28 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/components/FontFamilyPicker.tsx +293 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/components/FramePicker.tsx +69 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/components/InspectorPanel.tsx +25 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/components/Launcher.tsx +38 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/components/LayersPanel.tsx +277 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/components/LiveTime.tsx +101 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/components/MediaPool.tsx +1413 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/components/MediaPreview.tsx +188 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/components/MenuSelect.tsx +161 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/components/MgOutline.tsx +24 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/components/OperationHistory.tsx +184 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/components/PaneDivider.tsx +292 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/components/PasteAttrsDialog.tsx +69 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/components/PlaybackMenu.tsx +110 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/components/Popover.tsx +159 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/components/ProjectCover.tsx +60 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/components/ProjectHistoryControls.tsx +748 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/components/ProjectLayoutMenu.tsx +82 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/components/ProjectMenu.tsx +111 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/components/ProjectSources.tsx +587 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/components/ProjectView.tsx +3222 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/components/ProjectsLibrary.tsx +567 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/components/ProjectsView.tsx +1593 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/components/PropertiesSection.tsx +418 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/components/ResourceInspector.tsx +100 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/components/SelectionToolbar.tsx +157 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/components/SkillsLibrary.tsx +504 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/components/SourcePreview.tsx +464 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/components/SpendAsks.tsx +88 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/components/StageMaskOverlay.tsx +299 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/components/StageTransformFrame.tsx +246 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/components/SubtitleInspector.module.css +46 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/components/SubtitleInspector.tsx +884 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/components/SubtitleOverlay.tsx +148 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/components/SubtitleRow.tsx +419 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/components/TabStrip.tsx +188 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/components/Timeline.tsx +4911 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/components/TimelineMarkers.tsx +329 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/components/Toast.tsx +55 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/components/Tooltip.tsx +193 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/components/UpdateButton.tsx +104 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/components/ViewerBar.tsx +98 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/components/WhatsNew.tsx +147 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/components/dock-pane-bar.ts +16 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/components/export/ExportCenter.tsx +1502 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/components/export/ExportTray.tsx +284 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/components/film-stage-hit.ts +18 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/components/inspector-fields.tsx +863 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/components/inspector-look.tsx +1357 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/components/player-controls/controls-bar.tsx +397 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/components/player-controls/transport.tsx +294 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/components/replace-drop.ts +20 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/components/settings/AgentsSection.tsx +613 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/components/settings/CustomServices.tsx +104 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/components/settings/DiagnosticsGroup.tsx +202 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/components/settings/ModelsSection.tsx +179 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/components/settings/ProviderMark.tsx +24 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/components/settings/ProvidersSection.tsx +177 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/components/settings/SettingsModal.tsx +511 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/components/settings/SettingsSelect.tsx +84 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/components/settings/ShortcutsSection.tsx +291 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/components/settings/StorageGroup.tsx +119 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/components/settings/theme.ts +47 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/components/settings/ui.tsx +139 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/components/settings/use-settings.ts +10 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/components/stage-menu.tsx +283 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/components/timeline-head-extras.tsx +91 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/components/typing-target.ts +45 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/components/use-editor-tools.tsx +408 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/components/use-page-changes.ts +48 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/components/use-project-history.ts +113 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/components/useBlockDrag.ts +639 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/editor/Preview.tsx +426 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/editor/player.ts +558 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/editor/preview-frames.ts +36 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/editor/steps.ts +36 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/editor/undo.ts +156 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/editor/use-film.ts +212 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/editor/use-preview-renders.ts +89 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/globals.css +559 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/i18n/en.ts +1901 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/i18n/es.ts +1900 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/i18n/index.ts +130 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/i18n/ja.ts +1900 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/i18n/ko.ts +1896 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/i18n/words.ts +6 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/i18n/zh-CN.ts +1901 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/lib/agent-row.ts +21 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/lib/asset-timeline.ts +469 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/lib/audio-levels.ts +60 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/lib/batch-map.ts +28 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/lib/browser.ts +10 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/lib/canvas-fit.ts +116 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/lib/chat-marks.ts +114 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/lib/clip-attrs.ts +102 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/lib/clip-fade.ts +70 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/lib/clip-look.ts +520 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/lib/clip-mask.ts +536 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/lib/clip-replace.ts +60 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/lib/component-props.ts +128 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/lib/context-length.ts +12 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/lib/desktop-build.ts +44 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/lib/diagnostics.ts +68 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/lib/double-press.ts +22 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/lib/dropped-overrides.ts +139 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/lib/export-jobs.ts +191 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/lib/export-spec.ts +261 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/lib/field-input.ts +155 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/lib/film-clip-edits.ts +82 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/lib/film-frame.ts +134 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/lib/film-overrides.ts +107 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/lib/film-shape.ts +172 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/lib/film.ts +80 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/lib/font-menu.ts +236 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/lib/font-styles.ts +129 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/lib/freeze-frame.ts +49 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/lib/host.ts +438 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/lib/inspect-scrub.ts +26 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/lib/keymap-store.ts +74 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/lib/keymap.ts +529 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/lib/layers-tree.ts +133 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/lib/look.ts +83 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/lib/loudness.ts +58 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/lib/markers.ts +152 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/lib/media-bar.ts +58 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/lib/media-folders.ts +45 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/lib/media-place.ts +102 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/lib/media-queue.ts +107 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/lib/media-selection.ts +64 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/lib/menu-position.ts +77 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/lib/mg-transform.ts +111 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/lib/mixed.ts +3 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/lib/page-changes.ts +45 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/lib/picture-files.ts +19 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/lib/preview-prefs.ts +46 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/lib/preview-renders.ts +71 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/lib/project-delete.ts +20 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/lib/project-folders.ts +144 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/lib/project-history.ts +188 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/lib/project-sources.ts +283 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/lib/projects-page.ts +40 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/lib/provider-marks.ts +35 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/lib/providers.ts +163 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/lib/resource-drag.ts +131 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/lib/retry-image.ts +17 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/lib/saved-insert.ts +40 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/lib/saved.ts +125 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/lib/selection-toolbar.ts +158 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/lib/shortcut-hint.ts +21 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/lib/similar-layers.ts +46 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/lib/solo.ts +19 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/lib/stage-clip.ts +60 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/lib/stage-crop.ts +232 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/lib/stage-gesture.ts +277 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/lib/stage-layers.ts +71 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/lib/stage-mask.ts +176 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/lib/stage-measure.ts +53 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/lib/stage-types.ts +155 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/lib/studio-refs.ts +248 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/lib/studio-version.ts +41 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/lib/subtitle-cues.ts +238 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/lib/subtitles.ts +263 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/lib/tab-menu.ts +6 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/lib/template-controls.ts +131 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/lib/theme-changes.ts +31 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/lib/thumb-cache.ts +63 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/lib/thumb-cell.ts +8 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/lib/thumb-frame.ts +76 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/lib/thumb-pick.ts +42 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/lib/timecode.ts +161 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/lib/timeline-clipboard.ts +279 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/lib/timeline-drag.ts +589 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/lib/timeline-edit.ts +1138 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/lib/timeline-keys.ts +63 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/lib/timeline-layout.ts +1038 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/lib/timeline-nav.ts +160 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/lib/timeline-prefs.ts +73 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/lib/timeline-split.ts +40 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/lib/timeline-view.ts +105 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/lib/title.ts +39 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/lib/track-heights.ts +55 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/lib/track-lock.ts +27 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/lib/transitions.ts +459 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/lib/type-metrics.ts +83 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/lib/use-film-subtitles.ts +111 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/lib/use-fonts.ts +181 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/lib/use-loaded-thumbs.ts +91 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/lib/use-subtitle-edits.ts +134 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/lib/use-subtitle-font.ts +51 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/lib/use-subtitle-style.ts +68 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/lib/waveform-columns.ts +48 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/lib/web-update.ts +41 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/lib/whats-new.ts +401 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/lib/workspace-resources.ts +373 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/main.tsx +10 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/vite.config.ts +12 -0
- package/skill/assets/upstream/packages/shared/package.json +45 -0
- package/skill/assets/upstream/packages/shared/src/agent-activity.ts +263 -0
- package/skill/assets/upstream/packages/shared/src/contract.ts +285 -0
- package/skill/assets/upstream/packages/shared/src/index.ts +17 -0
- package/skill/assets/upstream/packages/shared/src/markdown-blocks.ts +252 -0
- package/skill/assets/upstream/packages/shared/src/modality.ts +4 -0
- package/skill/assets/upstream/packages/shared/src/prompt-reference.ts +113 -0
- package/skill/assets/upstream/packages/shared/src/title.ts +76 -0
- package/skill/assets/upstream/packages/shared/src/turn.ts +68 -0
- package/skill/assets/upstream/packages/shared/src/video.ts +26 -0
- package/skill/references/agent-components.md +33 -0
- package/skill/references/api-index.json +2693 -0
- package/skill/references/chat-components.md +65 -0
- package/skill/references/components.md +23 -0
- package/skill/references/core-components.md +44 -0
- package/skill/references/dependencies.md +22 -0
- package/skill/references/esm-package.md +48 -0
- package/skill/references/integration.md +43 -0
- package/skill/references/library-manifest.json +12 -0
- package/skill/references/source-manifest.json +325 -0
- package/skill/references/studio-components.md +24 -0
- package/skill/references/theme-motion.md +49 -0
- package/skill/references/troubleshooting.md +27 -0
- package/skill/references/verification.md +13 -0
- package/skill/scripts/check_dependencies.py +109 -0
- package/skill/scripts/inspect_api.py +60 -0
|
@@ -0,0 +1,299 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A mask edited on the picture (the inspector's Mask › Edit on picture): its outline over the clip or layer in hand,
|
|
3
|
+
* turned with it, and its handles — a press inside moves it (anywhere in the box for a line or a band), the squares
|
|
4
|
+
* resize it, the round knob above turns it, the knob below pulled outward feathers it. The geometry is lib/stage-mask's.
|
|
5
|
+
*
|
|
6
|
+
* A drag shows on the picture as it goes (the session's preview, a frame at a time) and is written once, at the
|
|
7
|
+
* release: one change, one undo step. Esc during a drag gives it up. Its presses are its own: none reaches the stage
|
|
8
|
+
* (which would move the clip or start a marquee); a press elsewhere goes on to the stage as usual.
|
|
9
|
+
*/
|
|
10
|
+
import * as React from 'react';
|
|
11
|
+
|
|
12
|
+
import { FRAME_BLUE, GestureHint, type FrameGeometry } from '@/components/StageTransformFrame';
|
|
13
|
+
import { useT } from '@/i18n';
|
|
14
|
+
import { HEART_D, STAR_D, type Mask } from '@/lib/clip-mask';
|
|
15
|
+
import {
|
|
16
|
+
draggedMask, featherPx, handlePivot, lineInBox, maskFrame, maskHandles, toLocal, type MaskDrag, type MaskHandleId,
|
|
17
|
+
type MaskSession,
|
|
18
|
+
} from '@/lib/stage-mask';
|
|
19
|
+
|
|
20
|
+
type P = { x: number; y: number };
|
|
21
|
+
|
|
22
|
+
/** A resize cursor for a handle turned `angle` degrees (as the frame's). */
|
|
23
|
+
function resizeCursor(angle: number): string {
|
|
24
|
+
const a = ((angle % 180) + 180) % 180;
|
|
25
|
+
if (a < 22.5 || a >= 157.5) return 'ew-resize';
|
|
26
|
+
if (a < 67.5) return 'nwse-resize';
|
|
27
|
+
if (a < 112.5) return 'ns-resize';
|
|
28
|
+
return 'nesw-resize';
|
|
29
|
+
}
|
|
30
|
+
const HANDLE_ANGLE: Record<MaskHandleId, number> = { e: 0, w: 0, n: 90, s: 90, nw: 45, se: 45, ne: 135, sw: 135 };
|
|
31
|
+
|
|
32
|
+
const fmt = (n: number) => String(Math.round(n * 10) / 10);
|
|
33
|
+
|
|
34
|
+
export function StageMaskOverlay({ frame, session }: {
|
|
35
|
+
/** The box the mask is drawn in, on the overlay (whole: a crop does not move a mask). */
|
|
36
|
+
frame: FrameGeometry;
|
|
37
|
+
session: MaskSession;
|
|
38
|
+
}) {
|
|
39
|
+
const t = useT();
|
|
40
|
+
const rootRef = React.useRef<HTMLDivElement | null>(null);
|
|
41
|
+
const sessionRef = React.useRef(session);
|
|
42
|
+
sessionRef.current = session;
|
|
43
|
+
/* what is drawn while dragging, and after the release until the written mask comes back as the session's */
|
|
44
|
+
const [live, setLive] = React.useState<Mask | null>(null);
|
|
45
|
+
const [hint, setHint] = React.useState<{ x: number; y: number; text: string } | null>(null);
|
|
46
|
+
const drag = React.useRef<{ kind: MaskDrag; m0: Mask; from: P; frame: FrameGeometry; el: Element; pointerId: number; last: Mask } | null>(null);
|
|
47
|
+
const previewRaf = React.useRef(0);
|
|
48
|
+
const settle = React.useRef<ReturnType<typeof setTimeout> | null>(null);
|
|
49
|
+
|
|
50
|
+
React.useEffect(() => {
|
|
51
|
+
if (drag.current) return;
|
|
52
|
+
setLive(null);
|
|
53
|
+
}, [session]);
|
|
54
|
+
React.useEffect(() => () => {
|
|
55
|
+
if (previewRaf.current) cancelAnimationFrame(previewRaf.current);
|
|
56
|
+
if (settle.current) clearTimeout(settle.current);
|
|
57
|
+
}, []);
|
|
58
|
+
|
|
59
|
+
const stagePoint = (e: { clientX: number; clientY: number }): P => {
|
|
60
|
+
const r = rootRef.current?.getBoundingClientRect();
|
|
61
|
+
return { x: e.clientX - (r?.left ?? 0), y: e.clientY - (r?.top ?? 0) };
|
|
62
|
+
};
|
|
63
|
+
const end = () => {
|
|
64
|
+
const d = drag.current;
|
|
65
|
+
drag.current = null;
|
|
66
|
+
if (previewRaf.current) { cancelAnimationFrame(previewRaf.current); previewRaf.current = 0; }
|
|
67
|
+
setHint(null);
|
|
68
|
+
try { if (d?.el.hasPointerCapture(d.pointerId)) d.el.releasePointerCapture(d.pointerId); } catch { /* gone already */ }
|
|
69
|
+
return d;
|
|
70
|
+
};
|
|
71
|
+
const cancel = () => {
|
|
72
|
+
const d = end();
|
|
73
|
+
if (!d) return;
|
|
74
|
+
setLive(null);
|
|
75
|
+
sessionRef.current.cancel();
|
|
76
|
+
};
|
|
77
|
+
const finish = () => {
|
|
78
|
+
const d = end();
|
|
79
|
+
if (!d) return;
|
|
80
|
+
if (JSON.stringify(d.last) === JSON.stringify(d.m0)) { setLive(null); return; }
|
|
81
|
+
setLive(d.last);
|
|
82
|
+
sessionRef.current.commit(d.last);
|
|
83
|
+
/* a write refused never comes back: the mask as written shows again */
|
|
84
|
+
if (settle.current) clearTimeout(settle.current);
|
|
85
|
+
settle.current = setTimeout(() => { if (!drag.current) setLive(null); }, 2000);
|
|
86
|
+
};
|
|
87
|
+
const step = (e: { clientX: number; clientY: number; shiftKey: boolean; altKey: boolean }) => {
|
|
88
|
+
const d = drag.current;
|
|
89
|
+
if (!d) return;
|
|
90
|
+
const p = stagePoint(e);
|
|
91
|
+
const box = { w: Math.max(1, d.frame.w), h: Math.max(1, d.frame.h) };
|
|
92
|
+
const next = draggedMask(d.m0, d.kind, box, d.from, toLocal(d.frame, p), { shift: e.shiftKey, alt: e.altKey });
|
|
93
|
+
d.last = next;
|
|
94
|
+
setLive(next);
|
|
95
|
+
const text = d.kind.kind === 'move' ? `X ${fmt(next.x)}% Y ${fmt(next.y)}%`
|
|
96
|
+
: d.kind.kind === 'turn' ? `${fmt(next.rotate)}°`
|
|
97
|
+
: d.kind.kind === 'feather' ? `${t('inspector.maskFeather')} ${fmt(next.feather)}%`
|
|
98
|
+
: next.shape === 'mirror' ? `${fmt(next.h)}%` : `${fmt(next.w)}% × ${fmt(next.h)}%`;
|
|
99
|
+
setHint({ x: p.x, y: p.y, text });
|
|
100
|
+
if (!previewRaf.current) {
|
|
101
|
+
previewRaf.current = requestAnimationFrame(() => {
|
|
102
|
+
previewRaf.current = 0;
|
|
103
|
+
if (drag.current) sessionRef.current.preview(drag.current.last);
|
|
104
|
+
});
|
|
105
|
+
}
|
|
106
|
+
};
|
|
107
|
+
|
|
108
|
+
/* Esc gives a drag up, before the stage hears it (it would let the clip go) */
|
|
109
|
+
React.useEffect(() => {
|
|
110
|
+
const onKey = (e: KeyboardEvent) => {
|
|
111
|
+
if (e.key !== 'Escape' || !drag.current) return;
|
|
112
|
+
e.preventDefault();
|
|
113
|
+
e.stopImmediatePropagation();
|
|
114
|
+
cancel();
|
|
115
|
+
};
|
|
116
|
+
window.addEventListener('keydown', onKey, true);
|
|
117
|
+
return () => window.removeEventListener('keydown', onKey, true);
|
|
118
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
119
|
+
}, []);
|
|
120
|
+
|
|
121
|
+
const m = live ?? session.mask;
|
|
122
|
+
const box = { w: Math.max(1, frame.w), h: Math.max(1, frame.h) };
|
|
123
|
+
const f = maskFrame(m, box);
|
|
124
|
+
const handles = maskHandles(m, box);
|
|
125
|
+
const fpx = featherPx(m, box);
|
|
126
|
+
const line = m.shape === 'linear' || m.shape === 'mirror';
|
|
127
|
+
const rad = (f.r * Math.PI) / 180;
|
|
128
|
+
const ux = { x: Math.cos(rad), y: Math.sin(rad) };
|
|
129
|
+
const uy = { x: -Math.sin(rad), y: Math.cos(rad) };
|
|
130
|
+
const at = (a: number, b: number): P => ({ x: f.cx + ux.x * a + uy.x * b, y: f.cy + ux.y * a + uy.y * b });
|
|
131
|
+
const segment = (off: number, key: string, dashed?: boolean) => {
|
|
132
|
+
const seg = lineInBox(at(0, off), ux, box.w, box.h);
|
|
133
|
+
return seg ? <Stroke key={key} d={`M${seg[0].x} ${seg[0].y}L${seg[1].x} ${seg[1].y}`} dashed={dashed} /> : null;
|
|
134
|
+
};
|
|
135
|
+
/* an ellipse `grow` px out of the mask's (its feather's outer edge) */
|
|
136
|
+
const ellipsePath = (grow: number) => {
|
|
137
|
+
const w = Math.max(0, f.w / 2 + grow);
|
|
138
|
+
const h = Math.max(0, f.h / 2 + grow);
|
|
139
|
+
return `M${f.cx - w} ${f.cy}a${w} ${h} 0 1 0 ${2 * w} 0a${w} ${h} 0 1 0 ${-2 * w} 0Z`;
|
|
140
|
+
};
|
|
141
|
+
|
|
142
|
+
return (
|
|
143
|
+
<div
|
|
144
|
+
ref={rootRef}
|
|
145
|
+
className="pointer-events-none absolute left-0 top-0 z-[6]"
|
|
146
|
+
onPointerDown={(e) => {
|
|
147
|
+
const part = (e.target as HTMLElement | null)?.closest('[data-mask-kind]');
|
|
148
|
+
if (!part || e.button !== 0) return;
|
|
149
|
+
e.stopPropagation();
|
|
150
|
+
e.preventDefault();
|
|
151
|
+
const kind = part.getAttribute('data-mask-kind');
|
|
152
|
+
const handle = part.getAttribute('data-mask-handle') as MaskHandleId | null;
|
|
153
|
+
const dk: MaskDrag | null = kind === 'move' ? { kind: 'move' } : kind === 'turn' ? { kind: 'turn' } : kind === 'feather' ? { kind: 'feather' }
|
|
154
|
+
: kind === 'resize' && handle ? { kind: 'resize', handle: handlePivot(handle) } : null;
|
|
155
|
+
if (!dk) return;
|
|
156
|
+
if (settle.current) { clearTimeout(settle.current); settle.current = null; }
|
|
157
|
+
part.setPointerCapture(e.pointerId);
|
|
158
|
+
drag.current = { kind: dk, m0: m, from: toLocal(frame, stagePoint(e)), frame, el: part, pointerId: e.pointerId, last: m };
|
|
159
|
+
}}
|
|
160
|
+
onPointerMove={(e) => { if (!drag.current) return; e.stopPropagation(); step(e); }}
|
|
161
|
+
onPointerUp={(e) => { if (!drag.current) return; e.stopPropagation(); step(e); finish(); }}
|
|
162
|
+
onPointerCancel={(e) => { if (!drag.current) return; e.stopPropagation(); finish(); }}
|
|
163
|
+
/* the system took the pointer: kept where it last was, as the stage's own gestures are */
|
|
164
|
+
onLostPointerCapture={(e) => { e.stopPropagation(); if (drag.current) finish(); }}
|
|
165
|
+
onDoubleClick={(e) => { if ((e.target as HTMLElement | null)?.closest('[data-mask-kind]')) e.stopPropagation(); }}
|
|
166
|
+
>
|
|
167
|
+
<div
|
|
168
|
+
className="absolute"
|
|
169
|
+
style={{
|
|
170
|
+
left: frame.cx - frame.w / 2,
|
|
171
|
+
top: frame.cy - frame.h / 2,
|
|
172
|
+
width: frame.w,
|
|
173
|
+
height: frame.h,
|
|
174
|
+
transform: frame.r ? `rotate(${frame.r}deg)` : undefined,
|
|
175
|
+
}}
|
|
176
|
+
>
|
|
177
|
+
{/* moved from inside the shape; a line or a band from anywhere in the box */}
|
|
178
|
+
<div
|
|
179
|
+
data-mask-kind="move"
|
|
180
|
+
aria-label={t('stageMask.move')}
|
|
181
|
+
className={`pointer-events-auto absolute ${drag.current?.kind.kind === 'move' ? 'cursor-grabbing' : 'cursor-move'}`}
|
|
182
|
+
style={line ? { inset: 0 } : {
|
|
183
|
+
left: f.cx - Math.max(f.w, 12) / 2,
|
|
184
|
+
top: f.cy - Math.max(f.h, 12) / 2,
|
|
185
|
+
width: Math.max(f.w, 12),
|
|
186
|
+
height: Math.max(f.h, 12),
|
|
187
|
+
transform: f.r ? `rotate(${f.r}deg)` : undefined,
|
|
188
|
+
}}
|
|
189
|
+
/>
|
|
190
|
+
<svg aria-hidden className="pointer-events-none absolute left-0 top-0 overflow-visible" width={box.w} height={box.h}>
|
|
191
|
+
{m.shape === 'linear' ? (
|
|
192
|
+
<>
|
|
193
|
+
{segment(0, 'line')}
|
|
194
|
+
{fpx > 0 ? <>{segment(fpx / 2, 'a', true)}{segment(-fpx / 2, 'b', true)}</> : null}
|
|
195
|
+
</>
|
|
196
|
+
) : m.shape === 'mirror' ? (
|
|
197
|
+
<>
|
|
198
|
+
{segment(-f.h / 2, 'top')}
|
|
199
|
+
{segment(f.h / 2, 'bottom')}
|
|
200
|
+
{fpx > 0 ? <>{segment(-f.h / 2 - fpx / 2, 'ta', true)}{segment(f.h / 2 + fpx / 2, 'ba', true)}</> : null}
|
|
201
|
+
</>
|
|
202
|
+
) : m.shape === 'ellipse' ? (
|
|
203
|
+
<>
|
|
204
|
+
<Stroke d={ellipsePath(0)} />
|
|
205
|
+
{fpx > 0 ? <Stroke d={ellipsePath(fpx / 2)} dashed /> : null}
|
|
206
|
+
</>
|
|
207
|
+
) : m.shape === 'rect' ? (
|
|
208
|
+
<g transform={`rotate(${f.r} ${f.cx} ${f.cy})`}>
|
|
209
|
+
<Stroke rect={{ x: f.cx - f.w / 2, y: f.cy - f.h / 2, w: f.w, h: f.h, r: Math.min((m.radius / 100) * Math.min(box.w, box.h), f.w / 2, f.h / 2) }} />
|
|
210
|
+
{fpx > 0 ? <Stroke rect={{ x: f.cx - f.w / 2 - fpx / 2, y: f.cy - f.h / 2 - fpx / 2, w: f.w + fpx, h: f.h + fpx, r: 0 }} dashed /> : null}
|
|
211
|
+
</g>
|
|
212
|
+
) : (
|
|
213
|
+
<g transform={`translate(${f.cx} ${f.cy}) rotate(${f.r}) scale(${Math.max(f.w, 0.01) / 2} ${Math.max(f.h, 0.01) / 2})`}>
|
|
214
|
+
<Stroke d={m.shape === 'star' ? STAR_D : HEART_D} scaled />
|
|
215
|
+
</g>
|
|
216
|
+
)}
|
|
217
|
+
{/* the knobs' stems */}
|
|
218
|
+
{handles.turn && !line ? <Stroke d={`M${at(0, -f.h / 2).x} ${at(0, -f.h / 2).y}L${handles.turn.x} ${handles.turn.y}`} thin /> : null}
|
|
219
|
+
{handles.feather ? (() => {
|
|
220
|
+
const from = line ? at(0, m.shape === 'mirror' ? -f.h / 2 : 0) : at(0, f.h / 2);
|
|
221
|
+
return <Stroke d={`M${from.x} ${from.y}L${handles.feather.at.x} ${handles.feather.at.y}`} thin dashed />;
|
|
222
|
+
})() : null}
|
|
223
|
+
{handles.turn && line ? <Stroke d={`M${f.cx} ${f.cy}L${handles.turn.x} ${handles.turn.y}`} thin /> : null}
|
|
224
|
+
</svg>
|
|
225
|
+
{/* the point a line or a band goes through */}
|
|
226
|
+
{line ? <Dot at={{ x: f.cx, y: f.cy }} size={8} kind="move" label={t('stageMask.move')} cursor="move" /> : null}
|
|
227
|
+
{handles.resize.map((h) => (
|
|
228
|
+
<div
|
|
229
|
+
key={h.id}
|
|
230
|
+
data-mask-kind="resize"
|
|
231
|
+
data-mask-handle={h.id}
|
|
232
|
+
aria-label={t('stageMask.resize')}
|
|
233
|
+
className="pointer-events-auto absolute flex items-center justify-center"
|
|
234
|
+
style={{
|
|
235
|
+
left: h.at.x - 7,
|
|
236
|
+
top: h.at.y - 7,
|
|
237
|
+
width: 14,
|
|
238
|
+
height: 14,
|
|
239
|
+
transform: f.r ? `rotate(${f.r}deg)` : undefined,
|
|
240
|
+
cursor: resizeCursor(HANDLE_ANGLE[h.id] + f.r + frame.r),
|
|
241
|
+
}}
|
|
242
|
+
>
|
|
243
|
+
<span className="block h-[8px] w-[8px] bg-white" style={{ border: `1px solid ${FRAME_BLUE}` }} />
|
|
244
|
+
</div>
|
|
245
|
+
))}
|
|
246
|
+
{handles.turn ? <Dot at={handles.turn} size={10} kind="turn" label={t('stageMask.turn')} cursor="grab" /> : null}
|
|
247
|
+
{handles.feather ? (
|
|
248
|
+
<Dot at={handles.feather.at} size={10} kind="feather" label={t('stageMask.feather')} cursor={resizeCursor(90 + f.r + frame.r)} filled />
|
|
249
|
+
) : null}
|
|
250
|
+
</div>
|
|
251
|
+
{hint ? <GestureHint x={hint.x} y={hint.y} text={hint.text} /> : null}
|
|
252
|
+
</div>
|
|
253
|
+
);
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
/** An outline: a dark line under a white one, to show on any picture. */
|
|
257
|
+
function Stroke({ d, rect, dashed, thin, scaled }: {
|
|
258
|
+
d?: string;
|
|
259
|
+
rect?: { x: number; y: number; w: number; h: number; r: number };
|
|
260
|
+
dashed?: boolean;
|
|
261
|
+
thin?: boolean;
|
|
262
|
+
/** Drawn in a scaled group: the stroke keeps its width on screen. */
|
|
263
|
+
scaled?: boolean;
|
|
264
|
+
}) {
|
|
265
|
+
const common = { fill: 'none', vectorEffect: scaled ? 'non-scaling-stroke' as const : undefined, strokeLinejoin: 'round' as const };
|
|
266
|
+
const shape = (stroke: string, width: number, dash?: string) => (rect
|
|
267
|
+
? <rect x={rect.x} y={rect.y} width={Math.max(0, rect.w)} height={Math.max(0, rect.h)} rx={rect.r} stroke={stroke} strokeWidth={width} strokeDasharray={dash} {...common} />
|
|
268
|
+
: <path d={d} stroke={stroke} strokeWidth={width} strokeDasharray={dash} {...common} />);
|
|
269
|
+
return (
|
|
270
|
+
<>
|
|
271
|
+
{shape('rgba(0,0,0,.45)', thin ? 2 : 3, dashed ? '4 3' : undefined)}
|
|
272
|
+
{shape(dashed ? 'rgba(255,255,255,.8)' : '#fff', thin ? 1 : 1.5, dashed ? '4 3' : undefined)}
|
|
273
|
+
</>
|
|
274
|
+
);
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
/** A round knob. */
|
|
278
|
+
function Dot({ at, size, kind, label, cursor, filled }: { at: P; size: number; kind: 'move' | 'turn' | 'feather'; label: string; cursor: string; filled?: boolean }) {
|
|
279
|
+
return (
|
|
280
|
+
<div
|
|
281
|
+
data-mask-kind={kind}
|
|
282
|
+
aria-label={label}
|
|
283
|
+
title={label}
|
|
284
|
+
className="pointer-events-auto absolute flex items-center justify-center"
|
|
285
|
+
style={{ left: at.x - 8, top: at.y - 8, width: 16, height: 16, cursor }}
|
|
286
|
+
>
|
|
287
|
+
<span
|
|
288
|
+
className="block rounded-full"
|
|
289
|
+
style={{
|
|
290
|
+
width: size,
|
|
291
|
+
height: size,
|
|
292
|
+
background: filled ? FRAME_BLUE : '#fff',
|
|
293
|
+
border: `1.5px solid ${filled ? '#fff' : FRAME_BLUE}`,
|
|
294
|
+
boxShadow: '0 0 0 0.5px rgba(0,0,0,.25), 0 1px 3px rgba(0,0,0,.3)',
|
|
295
|
+
}}
|
|
296
|
+
/>
|
|
297
|
+
</div>
|
|
298
|
+
);
|
|
299
|
+
}
|
package/skill/assets/upstream/packages/openfilm/studio/ui/src/components/StageTransformFrame.tsx
ADDED
|
@@ -0,0 +1,246 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The frame of the thing in hand on the stage, shared by a whole clip and a layer inside one.
|
|
3
|
+
*
|
|
4
|
+
* A 1px blue border and white corner squares with a blue edge (scale); an invisible ring outside the corners turns the
|
|
5
|
+
* pointer into the rotate cursor; invisible strips on the edges stretch one side (a layer's override scale has x and y;
|
|
6
|
+
* a video's or still's box takes any proportions, its CSS fitting the picture in it; a page's is never stretched, so
|
|
7
|
+
* its frame has corners only). A blue size label sits below the frame. While a gesture runs, a value tag follows the
|
|
8
|
+
* pointer: the position when moving, the size when scaling, the angle when turning.
|
|
9
|
+
*
|
|
10
|
+
* Geometry is the frame's own center, size and angle, not its bounding box: a turned thing has a turned frame.
|
|
11
|
+
*
|
|
12
|
+
* Four sets of data attributes: a whole clip's (`data-mg-kind` / `data-mg-handle`), a layer's (`data-layer-kind` /
|
|
13
|
+
* `data-layer-handle`), a crop's in crop mode (`data-crop-kind` / `data-crop-handle`) and several clips' together
|
|
14
|
+
* (`data-group-kind` / `data-group-handle`); one pointer press is routed by the set it lands on.
|
|
15
|
+
*/
|
|
16
|
+
/** The stage's "this one" blue: the frame, picked layers and linked outlines are drawn in it. */
|
|
17
|
+
export const FRAME_BLUE = '#0d99ff';
|
|
18
|
+
|
|
19
|
+
export type FrameCorner = 'nw' | 'ne' | 'se' | 'sw';
|
|
20
|
+
export type FrameEdge = 'n' | 'e' | 's' | 'w';
|
|
21
|
+
|
|
22
|
+
export interface FrameGeometry {
|
|
23
|
+
/** Center, in the stage overlay's px. */
|
|
24
|
+
cx: number;
|
|
25
|
+
cy: number;
|
|
26
|
+
/** Width and height before turning. */
|
|
27
|
+
w: number;
|
|
28
|
+
h: number;
|
|
29
|
+
/** Clockwise, degrees. */
|
|
30
|
+
r: number;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
const CORNERS: FrameCorner[] = ['nw', 'ne', 'se', 'sw'];
|
|
34
|
+
|
|
35
|
+
/** The handle ring's least size (px): 8px squares at least a square apart, with room left to press and drag. */
|
|
36
|
+
export const HANDLE_BOX_MIN = 28;
|
|
37
|
+
const EDGES: FrameEdge[] = ['n', 'e', 's', 'w'];
|
|
38
|
+
|
|
39
|
+
const CORNER_AT: Record<FrameCorner, { x: 0 | 1; y: 0 | 1 }> = {
|
|
40
|
+
nw: { x: 0, y: 0 }, ne: { x: 1, y: 0 }, se: { x: 1, y: 1 }, sw: { x: 0, y: 1 },
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
/*
|
|
44
|
+
* The rotate cursor: a quarter arc with an arrow at each end (browsers have no such cursor). Drawn for the
|
|
45
|
+
* top-right corner; other corners and turned frames turn it, cached in 15° steps.
|
|
46
|
+
*/
|
|
47
|
+
const ROTATE_CURSORS = new Map<number, string>();
|
|
48
|
+
function rotateCursor(angle: number): string {
|
|
49
|
+
const a = ((Math.round(angle / 15) * 15) % 360 + 360) % 360;
|
|
50
|
+
const hit = ROTATE_CURSORS.get(a);
|
|
51
|
+
if (hit) return hit;
|
|
52
|
+
const arc = 'M5 8A11 11 0 0 1 16 19M8.2 4.8L5 8l3.2 3.2M12.8 15.8L16 19l3.2-3.2';
|
|
53
|
+
const svg = '<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">'
|
|
54
|
+
+ `<g transform="rotate(${a} 12 12)" fill="none" stroke-linecap="round" stroke-linejoin="round">`
|
|
55
|
+
+ `<path d="${arc}" stroke="white" stroke-width="3.6"/>`
|
|
56
|
+
+ `<path d="${arc}" stroke="black" stroke-width="1.5"/>`
|
|
57
|
+
+ '</g></svg>';
|
|
58
|
+
const css = `url("data:image/svg+xml,${encodeURIComponent(svg)}") 12 12, crosshair`;
|
|
59
|
+
ROTATE_CURSORS.set(a, css);
|
|
60
|
+
return css;
|
|
61
|
+
}
|
|
62
|
+
const ROTATE_AT: Record<FrameCorner, number> = { ne: 0, se: 90, sw: 180, nw: 270 };
|
|
63
|
+
|
|
64
|
+
/** A resize cursor for an angle: after a 90° turn, the top edge drags sideways. */
|
|
65
|
+
function resizeCursor(angle: number): string {
|
|
66
|
+
const a = ((angle % 180) + 180) % 180;
|
|
67
|
+
if (a < 22.5 || a >= 157.5) return 'ew-resize';
|
|
68
|
+
if (a < 67.5) return 'nwse-resize';
|
|
69
|
+
if (a < 112.5) return 'ns-resize';
|
|
70
|
+
return 'nesw-resize';
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
const CORNER_ANGLE: Record<FrameCorner, number> = { nw: 45, ne: 135, se: 45, sw: 135 };
|
|
74
|
+
const EDGE_ANGLE: Record<FrameEdge, number> = { n: 90, s: 90, e: 0, w: 0 };
|
|
75
|
+
|
|
76
|
+
export function StageTransformFrame({
|
|
77
|
+
frame,
|
|
78
|
+
scope,
|
|
79
|
+
corners = 'scale',
|
|
80
|
+
edges = false,
|
|
81
|
+
rotate = true,
|
|
82
|
+
label,
|
|
83
|
+
moving = false,
|
|
84
|
+
bounds,
|
|
85
|
+
}: {
|
|
86
|
+
frame: FrameGeometry;
|
|
87
|
+
/**
|
|
88
|
+
* Which set of handle attributes (see the file head): `mg` for a whole clip, `layer` for a layer, `crop` for a crop,
|
|
89
|
+
* `group` for several clips selected together.
|
|
90
|
+
*/
|
|
91
|
+
scope: 'mg' | 'layer' | 'crop' | 'group';
|
|
92
|
+
corners?: 'scale' | 'none';
|
|
93
|
+
edges?: boolean;
|
|
94
|
+
rotate?: boolean;
|
|
95
|
+
/** The size label below the frame; null for none. */
|
|
96
|
+
label?: string | null;
|
|
97
|
+
/** Being moved: a light fill. */
|
|
98
|
+
moving?: boolean;
|
|
99
|
+
/** The stage's size in overlay px: the size label stays on it (below it is the viewer's own bar). */
|
|
100
|
+
bounds?: { w: number; h: number };
|
|
101
|
+
}) {
|
|
102
|
+
const w = Math.max(frame.w, 1);
|
|
103
|
+
const h = Math.max(frame.h, 1);
|
|
104
|
+
/*
|
|
105
|
+
* Handles sit on a frame at least HANDLE_BOX_MIN big: on something tiny (an icon, a thin line) corner squares on its
|
|
106
|
+
* own edges would pile up over it. The blue border keeps the true size and the handles go on the ring
|
|
107
|
+
* outside, the whole middle still draggable.
|
|
108
|
+
*/
|
|
109
|
+
const hw = Math.max(w, HANDLE_BOX_MIN);
|
|
110
|
+
const hh = Math.max(h, HANDLE_BOX_MIN);
|
|
111
|
+
const kindAttr = `data-${scope}-kind`;
|
|
112
|
+
const handleAttr = `data-${scope}-handle`;
|
|
113
|
+
const attrs = (kind: string, handle: string) => ({ [kindAttr]: kind, [handleAttr]: handle });
|
|
114
|
+
/* edge strips leave room for the corners; on a short frame in proportion, never below zero */
|
|
115
|
+
const insetX = Math.min(8, hw / 4);
|
|
116
|
+
const insetY = Math.min(8, hh / 4);
|
|
117
|
+
return (
|
|
118
|
+
<>
|
|
119
|
+
<div
|
|
120
|
+
className="pointer-events-none absolute"
|
|
121
|
+
style={{
|
|
122
|
+
left: frame.cx - hw / 2,
|
|
123
|
+
top: frame.cy - hh / 2,
|
|
124
|
+
width: hw,
|
|
125
|
+
height: hh,
|
|
126
|
+
transform: frame.r ? `rotate(${frame.r}deg)` : undefined,
|
|
127
|
+
transformOrigin: 'center',
|
|
128
|
+
}}
|
|
129
|
+
>
|
|
130
|
+
<div
|
|
131
|
+
{...attrs('move', 'move')}
|
|
132
|
+
/* inside a crop the hand pans the picture: the grab hand says so */
|
|
133
|
+
className={`pointer-events-auto absolute inset-0 ${moving ? 'cursor-grabbing' : scope === 'crop' ? 'cursor-grab' : 'cursor-default'}`}
|
|
134
|
+
/>
|
|
135
|
+
<div
|
|
136
|
+
aria-hidden
|
|
137
|
+
className="pointer-events-none absolute"
|
|
138
|
+
style={{
|
|
139
|
+
left: (hw - w) / 2,
|
|
140
|
+
top: (hh - h) / 2,
|
|
141
|
+
width: w,
|
|
142
|
+
height: h,
|
|
143
|
+
/* a border on something a pixel or two big would cover it: outline it from outside instead */
|
|
144
|
+
...(w < 3 || h < 3 ? { boxShadow: `0 0 0 1px ${FRAME_BLUE}` } : { border: `1px solid ${FRAME_BLUE}` }),
|
|
145
|
+
background: moving ? 'rgba(13,153,255,.06)' : 'transparent',
|
|
146
|
+
}}
|
|
147
|
+
/>
|
|
148
|
+
{edges ? EDGES.map((edge) => (
|
|
149
|
+
<div
|
|
150
|
+
key={edge}
|
|
151
|
+
{...attrs('stretch', edge)}
|
|
152
|
+
aria-hidden
|
|
153
|
+
className="pointer-events-auto absolute"
|
|
154
|
+
style={{
|
|
155
|
+
cursor: resizeCursor(EDGE_ANGLE[edge] + frame.r),
|
|
156
|
+
...(edge === 'n' ? { left: insetX, right: insetX, top: -4, height: 8 }
|
|
157
|
+
: edge === 's' ? { left: insetX, right: insetX, bottom: -4, height: 8 }
|
|
158
|
+
: edge === 'w' ? { top: insetY, bottom: insetY, left: -4, width: 8 }
|
|
159
|
+
: { top: insetY, bottom: insetY, right: -4, width: 8 }),
|
|
160
|
+
}}
|
|
161
|
+
/>
|
|
162
|
+
)) : null}
|
|
163
|
+
{rotate ? CORNERS.map((corner) => {
|
|
164
|
+
const at = CORNER_AT[corner];
|
|
165
|
+
return (
|
|
166
|
+
<div
|
|
167
|
+
key={`rot-${corner}`}
|
|
168
|
+
{...attrs('rotate', corner)}
|
|
169
|
+
aria-hidden
|
|
170
|
+
className="pointer-events-auto absolute"
|
|
171
|
+
style={{
|
|
172
|
+
width: 20,
|
|
173
|
+
height: 20,
|
|
174
|
+
left: at.x ? undefined : -20,
|
|
175
|
+
right: at.x ? -20 : undefined,
|
|
176
|
+
top: at.y ? undefined : -20,
|
|
177
|
+
bottom: at.y ? -20 : undefined,
|
|
178
|
+
cursor: rotateCursor(ROTATE_AT[corner] + frame.r),
|
|
179
|
+
}}
|
|
180
|
+
/>
|
|
181
|
+
);
|
|
182
|
+
}) : null}
|
|
183
|
+
{corners === 'scale' ? CORNERS.map((corner) => {
|
|
184
|
+
const at = CORNER_AT[corner];
|
|
185
|
+
return (
|
|
186
|
+
<div
|
|
187
|
+
key={corner}
|
|
188
|
+
{...attrs('scale', corner)}
|
|
189
|
+
aria-hidden
|
|
190
|
+
className="pointer-events-auto absolute flex items-center justify-center"
|
|
191
|
+
style={{
|
|
192
|
+
width: 14,
|
|
193
|
+
height: 14,
|
|
194
|
+
left: `calc(${at.x * 100}% - 7px)`,
|
|
195
|
+
top: `calc(${at.y * 100}% - 7px)`,
|
|
196
|
+
cursor: resizeCursor(CORNER_ANGLE[corner] + frame.r),
|
|
197
|
+
}}
|
|
198
|
+
>
|
|
199
|
+
<span
|
|
200
|
+
className="block h-[8px] w-[8px] bg-white"
|
|
201
|
+
style={{ border: `1px solid ${FRAME_BLUE}`, boxShadow: '0 0 0 0.5px rgba(0,0,0,.08)' }}
|
|
202
|
+
/>
|
|
203
|
+
</div>
|
|
204
|
+
);
|
|
205
|
+
}) : null}
|
|
206
|
+
</div>
|
|
207
|
+
{/* shown while dragging too: the frame moves and its size changes, and the label follows */}
|
|
208
|
+
{label ? <FrameLabel frame={{ ...frame, w: hw, h: hh }} text={label} {...(bounds ? { bounds } : {})} /> : null}
|
|
209
|
+
</>
|
|
210
|
+
);
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
/** The label's height (14px line + 1px padding each side) and its gap to the frame. */
|
|
214
|
+
const LABEL_H = 16;
|
|
215
|
+
const LABEL_GAP = 6;
|
|
216
|
+
|
|
217
|
+
/**
|
|
218
|
+
* The size label: 6px below the bounding box's bottom, centered; it does not turn with the frame. Something reaching
|
|
219
|
+
* the stage's bottom (a full-frame clip) has it just inside its bottom edge instead, clear of the viewer's bar.
|
|
220
|
+
*/
|
|
221
|
+
function FrameLabel({ frame, text, bounds }: { frame: FrameGeometry; text: string; bounds?: { w: number; h: number } }) {
|
|
222
|
+
const rad = (frame.r * Math.PI) / 180;
|
|
223
|
+
const halfH = (Math.abs(frame.w * Math.sin(rad)) + Math.abs(frame.h * Math.cos(rad))) / 2;
|
|
224
|
+
const below = frame.cy + halfH + LABEL_GAP;
|
|
225
|
+
const top = bounds && below + LABEL_H > bounds.h ? Math.max(0, Math.min(below, bounds.h) - LABEL_H - LABEL_GAP) : below;
|
|
226
|
+
return (
|
|
227
|
+
<div
|
|
228
|
+
className="pointer-events-none absolute z-[7] -translate-x-1/2 whitespace-nowrap rounded-[3px] px-1 py-[1px] text-[10px] font-medium leading-[14px] text-white tabular-nums"
|
|
229
|
+
style={{ left: frame.cx, top, background: FRAME_BLUE }}
|
|
230
|
+
>
|
|
231
|
+
{text}
|
|
232
|
+
</div>
|
|
233
|
+
);
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
/** The value tag next to the pointer while a gesture runs. */
|
|
237
|
+
export function GestureHint({ x, y, text }: { x: number; y: number; text: string }) {
|
|
238
|
+
return (
|
|
239
|
+
<div
|
|
240
|
+
className="pointer-events-none absolute z-[8] whitespace-nowrap rounded-[4px] px-1.5 py-[2px] text-[10.5px] font-medium leading-[15px] text-white tabular-nums shadow-[0_1px_4px_rgba(0,0,0,.25)]"
|
|
241
|
+
style={{ left: x + 14, top: y + 16, background: 'rgba(30,30,30,.92)' }}
|
|
242
|
+
>
|
|
243
|
+
{text}
|
|
244
|
+
</div>
|
|
245
|
+
);
|
|
246
|
+
}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
/* A quiet, consistent range control across Chromium, Safari and Firefox. */
|
|
2
|
+
.range {
|
|
3
|
+
appearance: none;
|
|
4
|
+
-webkit-appearance: none;
|
|
5
|
+
flex: 1;
|
|
6
|
+
min-width: 24px;
|
|
7
|
+
width: 0;
|
|
8
|
+
height: 20px;
|
|
9
|
+
margin: 0;
|
|
10
|
+
background: transparent;
|
|
11
|
+
cursor: pointer;
|
|
12
|
+
}
|
|
13
|
+
.range::-webkit-slider-runnable-track {
|
|
14
|
+
height: 3px;
|
|
15
|
+
border-radius: 3px;
|
|
16
|
+
background: var(--surface-3);
|
|
17
|
+
}
|
|
18
|
+
.range::-moz-range-track {
|
|
19
|
+
height: 3px;
|
|
20
|
+
border-radius: 3px;
|
|
21
|
+
background: var(--surface-3);
|
|
22
|
+
}
|
|
23
|
+
.range::-webkit-slider-thumb {
|
|
24
|
+
appearance: none;
|
|
25
|
+
-webkit-appearance: none;
|
|
26
|
+
width: 10px;
|
|
27
|
+
height: 10px;
|
|
28
|
+
margin-top: -3.5px;
|
|
29
|
+
border: 0;
|
|
30
|
+
border-radius: 50%;
|
|
31
|
+
background: var(--text-dim);
|
|
32
|
+
box-shadow: 0 0 0 2px var(--panel);
|
|
33
|
+
}
|
|
34
|
+
.range::-moz-range-thumb {
|
|
35
|
+
width: 10px;
|
|
36
|
+
height: 10px;
|
|
37
|
+
border: 0;
|
|
38
|
+
border-radius: 50%;
|
|
39
|
+
background: var(--text-dim);
|
|
40
|
+
box-shadow: 0 0 0 2px var(--panel);
|
|
41
|
+
}
|
|
42
|
+
.range:focus-visible {
|
|
43
|
+
outline: 1px solid var(--text-muted);
|
|
44
|
+
outline-offset: 2px;
|
|
45
|
+
border-radius: 3px;
|
|
46
|
+
}
|