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,116 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A film's canvas changing shape: the canvas takes the new shape with its short side kept (a
|
|
3
|
+
* 1920×1080 film made 3:4 is 1080×1440), and each picture is fitted to it on its own. A picture's place is read as
|
|
4
|
+
* two shares: its size as a share of the size that fits it whole in the canvas (1: it meets the canvas's edges
|
|
5
|
+
* one way), and its center as a share of the canvas from the canvas's center. Both are kept, so a full-frame video
|
|
6
|
+
* stays full-frame in any shape, a portrait photo on another clip fits by its own height, a title halfway up stays
|
|
7
|
+
* halfway up, and shapes picked one after another never shrink anything.
|
|
8
|
+
*
|
|
9
|
+
* A video or still without a box is the canvas whatever its shape (its picture fitted inside by CSS): it is left
|
|
10
|
+
* without one. A page is written its box. A page that sets no size of its own is laid out at the canvas's: it is
|
|
11
|
+
* given the old canvas as its `size`, so it is scaled as a video is rather than laid out again in the new shape.
|
|
12
|
+
*/
|
|
13
|
+
import { pictureRect } from '../../../../src/film-doc.mjs';
|
|
14
|
+
import { customFilmFrame, frameRatioOf, type FilmFrameId } from './film-frame.ts';
|
|
15
|
+
import { filmSrcKind, type FilmBox, type FilmSrcKind } from './film.ts';
|
|
16
|
+
|
|
17
|
+
type Size = { w: number; h: number };
|
|
18
|
+
|
|
19
|
+
/** Even sizes: H.264 samples chroma in 2×2 blocks and refuses odd dimensions. At most 8192 a side. */
|
|
20
|
+
const even = (n: number) => Math.max(2, Math.min(8192, Math.round(n / 2) * 2));
|
|
21
|
+
|
|
22
|
+
/** A canvas's sides, in px, and how far from square it may be (as a ratio typed for an export: 1:4 to 4:1). */
|
|
23
|
+
export const CANVAS_SIDE = { min: 16, max: 8192 } as const;
|
|
24
|
+
const CANVAS_STRETCH = 4;
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* A canvas `side` (its width or height) of `n` px, the other side kept: whole even px within CANVAS_SIDE, and no more
|
|
28
|
+
* than 4 times the other side or less than a quarter of it.
|
|
29
|
+
*/
|
|
30
|
+
export function canvasSide(n: number, other: number): number {
|
|
31
|
+
const lo = Math.max(CANVAS_SIDE.min, other / CANVAS_STRETCH);
|
|
32
|
+
const hi = Math.min(CANVAS_SIDE.max, other * CANVAS_STRETCH);
|
|
33
|
+
return Math.min(Math.floor(hi / 2) * 2, Math.max(Math.ceil(lo / 2) * 2, Math.round(n / 2) * 2));
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/** The canvas in another shape, its short side kept (a typed size is taken as it is elsewhere). */
|
|
37
|
+
export function canvasFor(stage: Size, frame: FilmFrameId): Size {
|
|
38
|
+
const ratio = frame === 'native' ? null : frameRatioOf(frame);
|
|
39
|
+
if (ratio == null) return { w: even(stage.w), h: even(stage.h) };
|
|
40
|
+
const short = Math.min(stage.w, stage.h);
|
|
41
|
+
return ratio >= 1 ? { w: even(short * ratio), h: even(short) } : { w: even(short), h: even(short / ratio) };
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* A picture clip as the fit needs it: its kind, its picture's own size (unknown: the old canvas), its box if any, and
|
|
46
|
+
* for a page, whether it sets no size of its own (`reflows`) and the `size` its clip gives it.
|
|
47
|
+
*/
|
|
48
|
+
export interface CanvasClip { id: string; kind: FilmSrcKind | null; own?: Size | null; box?: FilmBox | null; reflows?: boolean; size?: Size | null }
|
|
49
|
+
|
|
50
|
+
/** A clip on the new canvas: its box, and for a page laid out at the old canvas, that size. */
|
|
51
|
+
export interface CanvasFit { id: string; box: FilmBox; size?: Size }
|
|
52
|
+
|
|
53
|
+
/** The size of a picture shaped `ratio` (width / height) that fits whole in `canvas`, meeting its edges one way. */
|
|
54
|
+
const fitted = (ratio: number, canvas: Size): Size => (
|
|
55
|
+
canvas.w / canvas.h > ratio ? { w: canvas.h * ratio, h: canvas.h } : { w: canvas.w, h: canvas.w / ratio }
|
|
56
|
+
);
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* Each picture clip's box on the new canvas `to` (the old one is `from`), each clip fitted on its own: the same
|
|
60
|
+
* share of its fitted size, its center the same share of the canvas from the canvas's center. Sounds, and videos and
|
|
61
|
+
* stills without a box (they are the canvas), are left out.
|
|
62
|
+
*/
|
|
63
|
+
export function fitToCanvas(clips: readonly CanvasClip[], from: Size, to: Size): CanvasFit[] {
|
|
64
|
+
const out: CanvasFit[] = [];
|
|
65
|
+
for (const clip of clips) {
|
|
66
|
+
if (!clip.kind || clip.kind === 'sound') continue;
|
|
67
|
+
if (clip.kind !== 'page' && !clip.box) continue;
|
|
68
|
+
const own = clip.own && clip.own.w > 0 && clip.own.h > 0 ? clip.own : from;
|
|
69
|
+
const at = pictureRect(clip.kind, own, from, clip.box ?? undefined);
|
|
70
|
+
if (!(at.w > 0 && at.h > 0)) continue;
|
|
71
|
+
/* the box's shape; its picture's own when they differ only by rounding (a box written in whole px), so shapes
|
|
72
|
+
picked one after another do not drift */
|
|
73
|
+
const ownRatio = own.w / own.h;
|
|
74
|
+
const ratio = Math.abs(at.w / at.h / ownRatio - 1) < 0.01 ? ownRatio : at.w / at.h;
|
|
75
|
+
const share = at.w / fitted(ratio, from).w;
|
|
76
|
+
const fit = fitted(ratio, to);
|
|
77
|
+
const w = fit.w * share, h = fit.h * share;
|
|
78
|
+
const cx = to.w / 2 + ((at.x + at.w / 2 - from.w / 2) / from.w) * to.w;
|
|
79
|
+
const cy = to.h / 2 + ((at.y + at.h / 2 - from.h / 2) / from.h) * to.h;
|
|
80
|
+
/* whole px; an edge within 2 px of the canvas's meets it, so rounding never leaves a hairline of black */
|
|
81
|
+
const near = (v: number, edge: number) => (Math.abs(v - edge) <= 2 ? edge : Math.round(v));
|
|
82
|
+
const left = near(cx - w / 2, 0), top = near(cy - h / 2, 0);
|
|
83
|
+
const box: FilmBox = { x: left, y: top, w: near(cx + w / 2, to.w) - left, h: near(cy + h / 2, to.h) - top };
|
|
84
|
+
if (at.r) box.r = at.r;
|
|
85
|
+
out.push(clip.kind === 'page' && clip.reflows && !clip.size ? { id: clip.id, box, size: { w: from.w, h: from.h } } : { id: clip.id, box });
|
|
86
|
+
}
|
|
87
|
+
return out;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
/** Whether the stage has this ratio: its width within 2 px of it (a size made from a ratio is rounded to even px). */
|
|
91
|
+
export const shaped = (stage: Size, ratio: number) => Math.abs(stage.w - stage.h * ratio) <= 2;
|
|
92
|
+
|
|
93
|
+
/**
|
|
94
|
+
* The film's first picture's own size, which "Original" fits the canvas to: the earliest clip on the film with a
|
|
95
|
+
* picture whose size the preview knows (`spans`). A page that sets no size of its own is passed over: it is laid out at
|
|
96
|
+
* the canvas's size, so it has no shape of its own, and a film of such pages would always read as "Original".
|
|
97
|
+
*/
|
|
98
|
+
export function firstPictureSize(
|
|
99
|
+
clips: readonly { id: string; src: string; at?: number | null; sound?: unknown }[],
|
|
100
|
+
spans: readonly { id: string; w?: number; h?: number; reflows?: true }[],
|
|
101
|
+
): Size | null {
|
|
102
|
+
const sized = new Map(spans.filter((span) => span.w && span.h && !span.reflows).map((span) => [span.id, { w: span.w!, h: span.h! }]));
|
|
103
|
+
const first = clips
|
|
104
|
+
.filter((clip) => !clip.sound && filmSrcKind(clip.src) !== 'sound' && sized.has(clip.id))
|
|
105
|
+
.sort((a, b) => (a.at ?? 0) - (b.at ?? 0))[0];
|
|
106
|
+
return first ? sized.get(first.id) ?? null : null;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
/**
|
|
110
|
+
* The canvas's "Original" shape: the first picture's own (`original`), when there is one and it is between 1:4 and
|
|
111
|
+
* 4:1; and whether the stage has it now.
|
|
112
|
+
*/
|
|
113
|
+
export function originalShape(stage: Size, original: Size | null): { frame: FilmFrameId | null; current: boolean } {
|
|
114
|
+
const frame = original ? customFilmFrame(original.w, original.h) : null;
|
|
115
|
+
return { frame, current: Boolean(frame && original && shaped(stage, original.w / original.h)) };
|
|
116
|
+
}
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* What the app's chat points at in Studio (lib/host.ts StudioCommand `highlight` and `draft-refs`): the thing a pill
|
|
3
|
+
* hovered there stands for, lit while it is hovered, and the things the message being written references, numbered
|
|
4
|
+
* as the agent will read them ([1], [2], …). Pure, so `node --test` runs it (chat-marks.test.ts).
|
|
5
|
+
*/
|
|
6
|
+
import type { StageBox, StudioRef } from './host';
|
|
7
|
+
import type { FilmRange } from './studio-refs';
|
|
8
|
+
|
|
9
|
+
/** A clip as the timeline has it: its film.html id and its place (`film.html#<track>.<clip>`). */
|
|
10
|
+
export interface ClipKey { clipId?: string | null; loc?: string | null }
|
|
11
|
+
|
|
12
|
+
/** A box on the picture at its moment of the film (ms). */
|
|
13
|
+
export interface BoxAt { timeMs: number; box: StageBox }
|
|
14
|
+
|
|
15
|
+
/** A box is on the picture shown when it was pointed at within this much of the playhead (about a frame). */
|
|
16
|
+
export const BOX_AT_MS = 20;
|
|
17
|
+
|
|
18
|
+
/** The same clip: by film.html id when both have one (a clip keeps its id when tracks move), else by place. */
|
|
19
|
+
export function sameClip(a: ClipKey, b: ClipKey): boolean {
|
|
20
|
+
if (a.clipId && b.clipId) return a.clipId === b.clipId;
|
|
21
|
+
return Boolean(a.loc && a.loc === b.loc);
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* What a hovered pill lights: a clip's block (a layer's too: the clip it is in), a box on the picture (a layer where
|
|
26
|
+
* it was measured, a region), a span on the ruler (a range, a subtitle line, a moment as a span of none), a track's
|
|
27
|
+
* head, a file of the media pane.
|
|
28
|
+
*/
|
|
29
|
+
export interface ChatPoint {
|
|
30
|
+
clip: ClipKey | null;
|
|
31
|
+
box: BoxAt | null;
|
|
32
|
+
span: FilmRange | null;
|
|
33
|
+
track: number | null;
|
|
34
|
+
file: string | null;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
const ms = (s: number) => Math.round(s * 1000);
|
|
38
|
+
const NOTHING: ChatPoint = { clip: null, box: null, span: null, track: null, file: null };
|
|
39
|
+
|
|
40
|
+
export function chatPointOf(ref: StudioRef | null | undefined): ChatPoint | null {
|
|
41
|
+
if (!ref) return null;
|
|
42
|
+
switch (ref.kind) {
|
|
43
|
+
case 'clip': return ref.id || ref.loc ? { ...NOTHING, clip: { clipId: ref.id, loc: ref.loc } } : null;
|
|
44
|
+
case 'layer': return {
|
|
45
|
+
...NOTHING,
|
|
46
|
+
clip: ref.clipId ? { clipId: ref.clipId } : null,
|
|
47
|
+
box: ref.box && typeof ref.time === 'number' ? { timeMs: ms(ref.time), box: ref.box } : null,
|
|
48
|
+
};
|
|
49
|
+
case 'region': return { ...NOTHING, box: { timeMs: ms(ref.time), box: ref.box } };
|
|
50
|
+
case 'time': return { ...NOTHING, span: { startMs: ms(ref.time), endMs: ms(ref.time) } };
|
|
51
|
+
case 'range':
|
|
52
|
+
case 'subtitle': return { ...NOTHING, span: { startMs: ms(Math.min(ref.start, ref.end)), endMs: ms(Math.max(ref.start, ref.end)) } };
|
|
53
|
+
case 'track': return { ...NOTHING, track: ref.track };
|
|
54
|
+
case 'file': return { ...NOTHING, file: ref.path };
|
|
55
|
+
}
|
|
56
|
+
return null;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
/** The box, when the picture shows the moment it was pointed at; null otherwise. */
|
|
60
|
+
export function boxNow(at: BoxAt | null | undefined, nowMs: number): StageBox | null {
|
|
61
|
+
return at && Math.abs(at.timeMs - nowMs) <= BOX_AT_MS ? at.box : null;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* The message being written, as marks: its clips' blocks and its layers' and regions' boxes, each with its number
|
|
66
|
+
* (its place among the references, from 1). Other kinds take their number and show nowhere.
|
|
67
|
+
*/
|
|
68
|
+
export interface DraftMarks {
|
|
69
|
+
clips: ReadonlyArray<{ n: number; clip: ClipKey }>;
|
|
70
|
+
boxes: ReadonlyArray<{ n: number } & BoxAt>;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
export const NO_DRAFT: DraftMarks = { clips: [], boxes: [] };
|
|
74
|
+
|
|
75
|
+
export function draftMarksOf(refs: readonly StudioRef[]): DraftMarks {
|
|
76
|
+
if (!refs.length) return NO_DRAFT;
|
|
77
|
+
const clips: Array<{ n: number; clip: ClipKey }> = [];
|
|
78
|
+
const boxes: Array<{ n: number } & BoxAt> = [];
|
|
79
|
+
refs.forEach((ref, i) => {
|
|
80
|
+
const n = i + 1;
|
|
81
|
+
if (ref.kind === 'clip' && (ref.id || ref.loc)) clips.push({ n, clip: { clipId: ref.id, loc: ref.loc } });
|
|
82
|
+
else if (ref.kind === 'layer' && ref.box && typeof ref.time === 'number') boxes.push({ n, timeMs: ms(ref.time), box: ref.box });
|
|
83
|
+
else if (ref.kind === 'region') boxes.push({ n, timeMs: ms(ref.time), box: ref.box });
|
|
84
|
+
});
|
|
85
|
+
return { clips, boxes };
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
/** A block's numbers in the message being written (none: it is not referenced). */
|
|
89
|
+
export function draftNumbersOf(marks: DraftMarks, clip: ClipKey): number[] {
|
|
90
|
+
return marks.clips.filter((m) => sameClip(m.clip, clip)).map((m) => m.n);
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
/** The boxes of the message being written that are on the picture shown now. */
|
|
94
|
+
export function draftBoxesAt(marks: DraftMarks, nowMs: number): Array<{ n: number; box: StageBox }> {
|
|
95
|
+
return marks.boxes.filter((m) => boxNow(m, nowMs)).map(({ n, box }) => ({ n, box }));
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
/** What the picture draws for the chat: the hovered pill's clip (by place) or box, and the numbered boxes. */
|
|
99
|
+
export interface PictureMarks {
|
|
100
|
+
clipLoc: string | null;
|
|
101
|
+
box: StageBox | null;
|
|
102
|
+
numbered: ReadonlyArray<{ n: number; box: StageBox }>;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
const sameBox = (a: StageBox | null | undefined, b: StageBox | null | undefined) =>
|
|
106
|
+
a === b || Boolean(a && b && a.x === b.x && a.y === b.y && a.w === b.w && a.h === b.h);
|
|
107
|
+
|
|
108
|
+
/** By content: the picture is memoized, and these are made anew as the playhead moves. */
|
|
109
|
+
export function samePictureMarks(a: PictureMarks | null | undefined, b: PictureMarks | null | undefined): boolean {
|
|
110
|
+
if (a === b) return true;
|
|
111
|
+
if (!a || !b) return !(a?.clipLoc || a?.box || a?.numbered.length || b?.clipLoc || b?.box || b?.numbered.length);
|
|
112
|
+
return a.clipLoc === b.clipLoc && sameBox(a.box, b.box)
|
|
113
|
+
&& a.numbered.length === b.numbered.length && a.numbered.every((m, i) => m.n === b.numbered[i]!.n && sameBox(m.box, b.numbered[i]!.box));
|
|
114
|
+
}
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A clip's attributes copied onto other clips (copy / paste attributes, ⌘⇧C / ⌘⇧V): the groups its paste dialog
|
|
3
|
+
* offers, all ticked unless unticked —
|
|
4
|
+
* · `place`: where the picture sits and how big it is, turned (`box`);
|
|
5
|
+
* · `blend`: how it shows through (`opacity`, `mix-blend-mode` in its style; the rest of its style stays);
|
|
6
|
+
* · `volume`: how loud its sound is;
|
|
7
|
+
* · `fade`: its fade in and fade out, shortened to fit a shorter clip.
|
|
8
|
+
* A picture's groups go onto pictures, the sound's onto clips with sound; what a clip cannot take is left out.
|
|
9
|
+
*
|
|
10
|
+
* Pure: the editor reads the copy from film.html and writes the edits it gives back (lib/film-clip-edits).
|
|
11
|
+
*/
|
|
12
|
+
import { declared, withDeclarations } from './clip-look.ts';
|
|
13
|
+
import { fadeMsOf } from './clip-fade.ts';
|
|
14
|
+
import { filmSrcKind } from './film.ts';
|
|
15
|
+
import type { ClipEdit } from './film-clip-edits';
|
|
16
|
+
|
|
17
|
+
export type AttrGroup = 'place' | 'blend' | 'volume' | 'fade';
|
|
18
|
+
|
|
19
|
+
type Box = { x: number; y: number; w?: number; h?: number; r?: number };
|
|
20
|
+
/** What a clip's attributes are read from: its row in film.html (lib/film's FilmClip, api's Clip). */
|
|
21
|
+
export interface AttrClip {
|
|
22
|
+
id: string;
|
|
23
|
+
src: string;
|
|
24
|
+
sound?: boolean;
|
|
25
|
+
box?: Box;
|
|
26
|
+
style?: string;
|
|
27
|
+
volume?: number;
|
|
28
|
+
overrides?: readonly unknown[];
|
|
29
|
+
}
|
|
30
|
+
export const ATTR_GROUPS: readonly AttrGroup[] = ['place', 'blend', 'volume', 'fade'];
|
|
31
|
+
|
|
32
|
+
export interface CopiedAttrs {
|
|
33
|
+
/** The clip copied from, for saying so. */
|
|
34
|
+
from: string;
|
|
35
|
+
picture: boolean;
|
|
36
|
+
sound: boolean;
|
|
37
|
+
place: Box | null;
|
|
38
|
+
blend: { opacity: string | null; mode: string | null };
|
|
39
|
+
volume: number;
|
|
40
|
+
/** Seconds. */
|
|
41
|
+
fade: [number, number];
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/** What a clip shows and what it plays: a picture (a page, a video, a still), a sound (a video, a sound). */
|
|
45
|
+
function sides(clip: Pick<AttrClip, 'src' | 'sound'>): { picture: boolean; sound: boolean } {
|
|
46
|
+
const kind = clip.sound ? 'sound' : filmSrcKind(clip.src);
|
|
47
|
+
return { picture: kind !== 'sound', sound: kind === 'video' || kind === 'sound' };
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/** The attributes of a clip, as film.html has them. */
|
|
51
|
+
export function attrsOf(clip: AttrClip): CopiedAttrs {
|
|
52
|
+
const style = clip.style ?? '';
|
|
53
|
+
const [fadeIn, fadeOut] = fadeMsOf(clip);
|
|
54
|
+
return {
|
|
55
|
+
from: clip.id,
|
|
56
|
+
...sides(clip),
|
|
57
|
+
place: clip.box ? { ...clip.box } : null,
|
|
58
|
+
blend: { opacity: declared(style, 'opacity') ?? null, mode: declared(style, 'mix-blend-mode') ?? null },
|
|
59
|
+
volume: clip.volume ?? 1,
|
|
60
|
+
fade: [fadeIn / 1000, fadeOut / 1000],
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/** The groups a copy has anything for: a picture's for a picture, the sound's for a sound. */
|
|
65
|
+
export function groupsOf(attrs: CopiedAttrs): AttrGroup[] {
|
|
66
|
+
return ATTR_GROUPS.filter((g) => (g === 'place' || g === 'blend' ? attrs.picture : g === 'volume' ? attrs.sound : true));
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
export interface AttrTarget {
|
|
70
|
+
loc: string;
|
|
71
|
+
clip: AttrClip;
|
|
72
|
+
/** Its length on the film, seconds: a fade longer than the clip is shortened. */
|
|
73
|
+
lengthS: number;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
/** The fade a clip `lengthS` long can take: the copy's, both ends shortened alike when together they are longer. */
|
|
77
|
+
function fitted([fadeIn, fadeOut]: [number, number], lengthS: number): [number, number] {
|
|
78
|
+
const total = fadeIn + fadeOut;
|
|
79
|
+
if (total <= lengthS || total <= 0) return [fadeIn, fadeOut];
|
|
80
|
+
const k = lengthS / total;
|
|
81
|
+
return [Math.floor(fadeIn * k * 1000) / 1000, Math.floor(fadeOut * k * 1000) / 1000];
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
/** The edits that put the ticked groups of a copy onto these clips (not onto the clip copied from). */
|
|
85
|
+
export function pasteAttrs(attrs: CopiedAttrs, groups: ReadonlySet<AttrGroup>, targets: readonly AttrTarget[]): ClipEdit[] {
|
|
86
|
+
const out: ClipEdit[] = [];
|
|
87
|
+
for (const { loc, clip, lengthS } of targets) {
|
|
88
|
+
if (clip.id === attrs.from) continue;
|
|
89
|
+
const can = sides(clip);
|
|
90
|
+
if (can.picture && attrs.picture && groups.has('place')) out.push({ loc, prop: 'box', value: attrs.place ? { ...attrs.place } : null });
|
|
91
|
+
if (can.picture && attrs.picture && groups.has('blend')) {
|
|
92
|
+
const style = withDeclarations(clip.style ?? '', { opacity: attrs.blend.opacity, 'mix-blend-mode': attrs.blend.mode });
|
|
93
|
+
if (style !== (clip.style ?? '')) out.push({ loc, prop: 'style', value: style || null });
|
|
94
|
+
}
|
|
95
|
+
if (can.sound && attrs.sound && groups.has('volume')) out.push({ loc, prop: 'volume', value: attrs.volume });
|
|
96
|
+
if (groups.has('fade')) {
|
|
97
|
+
const [fadeIn, fadeOut] = fitted(attrs.fade, lengthS);
|
|
98
|
+
out.push({ loc, prop: 'fade', value: fadeIn > 0 || fadeOut > 0 ? [fadeIn, fadeOut] : null });
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
return out;
|
|
102
|
+
}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A clip's fades on the timeline: the handles at its top corners, dragged inward, and the ramp drawn over it.
|
|
3
|
+
*
|
|
4
|
+
* A fade is kept in film.html as the clip's own entry of its `overrides` (`{ "fade": [in, out] }`, seconds; see
|
|
5
|
+
* SPEC §1): the timeline writes it with the `fade` prop (studio/server/ops.mjs), one edit for the clip and the clips
|
|
6
|
+
* linked to it, so a picture and the sound taken off it fade together.
|
|
7
|
+
*
|
|
8
|
+
* Pure: the timeline draws a drag's fade from here while the hand is still on the handle, and writes it on release.
|
|
9
|
+
*/
|
|
10
|
+
import type { Op } from '../api.ts';
|
|
11
|
+
import { clipFade } from '../../../../src/film-doc.mjs';
|
|
12
|
+
|
|
13
|
+
/** In and out, in ms. */
|
|
14
|
+
export type FadeMs = readonly [number, number];
|
|
15
|
+
export type FadeEdge = 'in' | 'out';
|
|
16
|
+
|
|
17
|
+
/** A clip's fades in ms (`[0, 0]` without any), from its film.html row. */
|
|
18
|
+
export function fadeMsOf(clip: { overrides?: readonly unknown[] } | null | undefined): FadeMs {
|
|
19
|
+
const fade = clipFade(clip);
|
|
20
|
+
return fade ? [Math.round(fade[0] * 1000), Math.round(fade[1] * 1000)] : [0, 0];
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* The fade a handle dragged to `pointerMs` sets on a clip over `[startMs, endMs)`: from its start (in) or back from
|
|
25
|
+
* its end (out), on the frame grid (`frameMs` a frame), never past where the other fade begins, never below 0.
|
|
26
|
+
*/
|
|
27
|
+
export function fadeFromPointer(edge: FadeEdge, pointerMs: number, clip: { startMs: number; endMs: number }, other: number, frameMs: number): number {
|
|
28
|
+
const room = Math.max(0, clip.endMs - clip.startMs - other);
|
|
29
|
+
const raw = edge === 'in' ? pointerMs - clip.startMs : clip.endMs - pointerMs;
|
|
30
|
+
const snapped = frameMs > 0 ? Math.round(raw / frameMs) * frameMs : raw;
|
|
31
|
+
/* a whole frame less when the frame nearest does not fit, so it stays on the grid */
|
|
32
|
+
const fit = snapped > room && frameMs > 0 ? Math.floor(room / frameMs) * frameMs : snapped;
|
|
33
|
+
/* to the microsecond: frames of 33.33… ms gather float noise */
|
|
34
|
+
return Math.round(Math.max(0, Math.min(room, fit)) * 1000) / 1000;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/** Where a fade's handle sits in a clip `widthPx` wide: px from its left edge. */
|
|
38
|
+
export function fadeHandleX(edge: FadeEdge, fadeMs: number, widthPx: number, pxPerMs: number): number {
|
|
39
|
+
const px = Math.min(widthPx, fadeMs * pxPerMs);
|
|
40
|
+
return edge === 'in' ? px : widthPx - px;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/** A clip as a fade edit sees it. */
|
|
44
|
+
export interface FadeClip { id: string; startMs: number; endMs: number; fade: FadeMs; locked?: boolean }
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* One fade set on a clip and on the clips going with it (`with`: those linked to it, unless ⌥), each that has the same
|
|
48
|
+
* edge within `tolMs` of the clip's: a picture and its sound end together, so they fade together. Fitted to each one's
|
|
49
|
+
* length; none on a locked track. The edits film.html takes, by clip id.
|
|
50
|
+
*/
|
|
51
|
+
export function fadeEdits(edge: FadeEdge, ms: number, clip: FadeClip, others: readonly FadeClip[] = [], tolMs = 1): { clip: string; prop: 'fade'; value: [number, number] }[] {
|
|
52
|
+
const at = (c: FadeClip) => (edge === 'in' ? c.startMs : c.endMs);
|
|
53
|
+
const all = [clip, ...others.filter((c) => c.id !== clip.id && Math.abs(at(c) - at(clip)) <= tolMs)];
|
|
54
|
+
return all.filter((c) => !c.locked).flatMap((c) => {
|
|
55
|
+
const len = c.endMs - c.startMs;
|
|
56
|
+
const other = edge === 'in' ? c.fade[1] : c.fade[0];
|
|
57
|
+
const own = Math.max(0, Math.min(ms, len - other));
|
|
58
|
+
const next: [number, number] = edge === 'in' ? [own, c.fade[1]] : [c.fade[0], own];
|
|
59
|
+
if (Math.round(next[0]) === Math.round(c.fade[0]) && Math.round(next[1]) === Math.round(c.fade[1])) return [];
|
|
60
|
+
return [{ clip: c.id, prop: 'fade' as const, value: [secs(next[0]), secs(next[1])] }];
|
|
61
|
+
});
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/** The edit of fades as an operation (one write, one undo step); null when nothing changes. */
|
|
65
|
+
export function fadeOp(edits: ReturnType<typeof fadeEdits>): Op | null {
|
|
66
|
+
return edits.length ? { op: 'props', edits } : null;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/** ms → seconds to the millisecond, as film.html keeps them. */
|
|
70
|
+
export const secs = (ms: number): number => Math.round(ms) / 1000;
|