@dfosco/storyboard 0.7.0 → 0.8.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/assets/favicon.svg +12 -0
- package/dist/storyboard-ui.css +1 -1
- package/dist/storyboard-ui.js +13907 -10816
- package/dist/storyboard-ui.js.map +1 -1
- package/dist/tailwind.css +1 -1
- package/package.json +138 -127
- package/scaffold/AGENTS.md +9 -7
- package/scaffold/README.md +18 -0
- package/scaffold/deploy.yml +21 -0
- package/scaffold/gitignore +8 -14
- package/scaffold/preview.yml +40 -0
- package/scaffold/{manifest.json → scaffold.config.json} +73 -3
- package/scaffold/scripts/aggregate-artifacts.mjs +257 -0
- package/scaffold/skills/canvas/SKILL.md +1 -1
- package/scaffold/skills/migrate-0.5.0/SKILL.md +1 -1
- package/scaffold/skills/ship/SKILL.md +2 -2
- package/scaffold/skills/worktree/SKILL.md +1 -1
- package/scaffold/src/_prototype.jsx +17 -0
- package/scaffold/src/_story.jsx +13 -0
- package/scaffold/src/library/README.md +34 -0
- package/scaffold/src/library/_app.jsx +53 -0
- package/scaffold/src/library/_app.module.css +8 -0
- package/scaffold/src/library/create.jsx +10 -0
- package/scaffold/src/library/index.jsx +14 -0
- package/scaffold/src/library/mount.jsx +52 -0
- package/scaffold/src/library/prototypes-entry.jsx +57 -0
- package/scaffold/src/library/routes.jsx +205 -0
- package/scaffold/src/library/viewfinder.jsx +13 -0
- package/scaffold/src/library/workspace.jsx +17 -0
- package/scripts/aggregate-artifacts.mjs +257 -0
- package/src/core/artifact/operations.js +19 -13
- package/src/core/autosync/server.test.js +1 -1
- package/src/core/canvas/githubEmbeds.js +12 -0
- package/src/core/canvas/githubEmbeds.test.js +71 -2
- package/src/core/canvas/hot-pool.js +10 -11
- package/src/core/canvas/materializer.js +39 -13
- package/src/core/canvas/server.js +324 -69
- package/src/core/canvas/server.test.js +365 -2
- package/src/core/canvas/terminal-server.js +144 -57
- package/src/core/canvas/undoRedo.js +174 -0
- package/src/core/canvas/undoRedo.test.js +250 -0
- package/src/core/cli/buildManifest.js +34 -0
- package/src/core/cli/canvasRedo.js +44 -0
- package/src/core/cli/canvasUndo.js +40 -0
- package/src/core/cli/create.js +116 -18
- package/src/core/cli/dev.js +23 -35
- package/src/core/cli/index.js +21 -0
- package/src/core/cli/schemas.js +2 -3
- package/src/core/cli/serverUrl.js +24 -0
- package/src/core/cli/setup.js +14 -25
- package/src/core/cli/terminal-welcome.js +12 -6
- package/src/core/cli/updateVersion.js +42 -2
- package/src/core/cli/workleaf.js +140 -0
- package/src/core/comments/api.js +1 -1
- package/src/core/comments/queries.js +3 -0
- package/src/core/comments/ui/CommentWindow.jsx +3 -2
- package/src/core/data/artifactIndex.js +235 -0
- package/src/core/data/artifactIndex.test.js +203 -0
- package/src/core/data/artifactManifest.js +290 -0
- package/src/core/data/artifactManifest.test.js +207 -0
- package/src/core/data/viewfinder.js +47 -7
- package/src/core/index.js +6 -1
- package/src/core/lib/components/ui/avatar/avatar-fallback.jsx +2 -2
- package/src/core/lib/components/ui/avatar/avatar-image.jsx +2 -2
- package/src/core/lib/components/ui/avatar/avatar.jsx +2 -2
- package/src/core/lib/components/ui/checkbox/checkbox.jsx +12 -9
- package/src/core/lib/components/ui/dialog/dialog-content.jsx +45 -31
- package/src/core/lib/components/ui/dialog/dialog-trigger.jsx +9 -5
- package/src/core/lib/components/ui/dialog/dialog.jsx +12 -3
- package/src/core/lib/components/ui/dialog/dialog.module.css +118 -0
- package/src/core/lib/components/ui/dialog/index.js +4 -34
- package/src/core/lib/components/ui/dropdown-menu/dropdown-menu-checkbox-group.jsx +3 -3
- package/src/core/lib/components/ui/dropdown-menu/dropdown-menu-checkbox-item.jsx +19 -9
- package/src/core/lib/components/ui/dropdown-menu/dropdown-menu-content.jsx +8 -8
- package/src/core/lib/components/ui/dropdown-menu/dropdown-menu-group-heading.jsx +2 -2
- package/src/core/lib/components/ui/dropdown-menu/dropdown-menu-group.jsx +2 -2
- package/src/core/lib/components/ui/dropdown-menu/dropdown-menu-item.jsx +15 -4
- package/src/core/lib/components/ui/dropdown-menu/dropdown-menu-portal.jsx +2 -2
- package/src/core/lib/components/ui/dropdown-menu/dropdown-menu-radio-group.jsx +2 -2
- package/src/core/lib/components/ui/dropdown-menu/dropdown-menu-radio-item.jsx +14 -7
- package/src/core/lib/components/ui/dropdown-menu/dropdown-menu-separator.jsx +2 -2
- package/src/core/lib/components/ui/dropdown-menu/dropdown-menu-sub-content.jsx +8 -4
- package/src/core/lib/components/ui/dropdown-menu/dropdown-menu-sub-trigger.jsx +4 -4
- package/src/core/lib/components/ui/dropdown-menu/dropdown-menu-sub.jsx +2 -2
- package/src/core/lib/components/ui/dropdown-menu/dropdown-menu-trigger.jsx +8 -2
- package/src/core/lib/components/ui/dropdown-menu/dropdown-menu.jsx +2 -2
- package/src/core/lib/components/ui/label/label.jsx +1 -2
- package/src/core/lib/components/ui/panel/panel-close.jsx +7 -4
- package/src/core/lib/components/ui/panel/panel-content.jsx +7 -9
- package/src/core/lib/components/ui/panel/panel-title.jsx +3 -3
- package/src/core/lib/components/ui/panel/panel.jsx +11 -2
- package/src/core/lib/components/ui/separator/separator.jsx +6 -4
- package/src/core/lib/components/ui/tooltip/tooltip-content.jsx +7 -6
- package/src/core/lib/components/ui/tooltip/tooltip-trigger.jsx +13 -6
- package/src/core/lib/components/ui/tooltip/tooltip.jsx +5 -5
- package/src/core/mountStoryboardCore.js +234 -74
- package/src/core/mountStoryboardCore.test.js +174 -0
- package/src/core/rename-watcher/watcher.js +329 -36
- package/src/core/rename-watcher/watcher.test.js +253 -0
- package/src/core/scaffold/fragments.js +287 -0
- package/src/core/scaffold/fragments.test.js +401 -0
- package/src/core/scaffold/index.js +291 -0
- package/src/core/scaffold/migrateLegacyGitignore.js +157 -0
- package/src/core/scaffold/scaffold-integration.test.js +247 -0
- package/src/core/scaffold.js +4 -97
- package/src/core/stores/configSchema.js +41 -2
- package/src/core/stores/recentArtifacts.js +49 -2
- package/src/core/stores/recentArtifacts.test.js +59 -6
- package/src/core/stores/themeBootstrap.js +264 -0
- package/src/core/stores/themeBootstrap.test.js +211 -0
- package/src/core/stores/themeStore.test.js +154 -0
- package/src/core/stores/themeStore.ts +235 -220
- package/src/core/styles/generateThemesCss.js +63 -0
- package/src/core/styles/tailwind.css +12 -4
- package/src/core/styles/workspace-chrome.css +30 -0
- package/src/core/tools/handlers/paletteTheme.js +11 -8
- package/src/core/ui/ActionMenuButton.jsx +2 -1
- package/src/core/ui/CanvasCreateMenu.jsx +1 -19
- package/src/core/ui/CoreUIBar.jsx +10 -7
- package/src/core/ui/ThemeMenuButton.jsx +45 -30
- package/src/core/vite/server-plugin.js +36 -0
- package/src/core/workleaf/cleanup.js +102 -0
- package/src/core/workleaf/create.js +199 -0
- package/src/core/workleaf/delete.js +101 -0
- package/src/core/workleaf/list.js +57 -0
- package/src/core/workleaf/merge.js +238 -0
- package/src/core/workleaf/paths.js +146 -0
- package/src/core/workleaf/paths.test.js +230 -0
- package/src/core/workshop/features/createCanvas/CreateCanvasForm.jsx +28 -21
- package/src/core/workshop/features/createFlow/server.js +5 -1
- package/src/core/workshop/features/createPrototype/server.js +5 -1
- package/src/core/workshop/features/templateIndex.js +28 -1
- package/src/core/worktree/port.js +48 -5
- package/src/core/worktree/port.test.js +42 -0
- package/src/internals/ArtifactForm/ArtifactForm.jsx +173 -112
- package/src/internals/ArtifactForm/ArtifactForm.module.css +48 -66
- package/src/internals/ArtifactForm/artifactSchemas.js +40 -5
- package/src/internals/BaseUiForm/BaseUiForm.jsx +293 -0
- package/src/internals/BaseUiForm/BaseUiForm.module.css +542 -0
- package/src/internals/BranchesDropdown/BranchesDropdown.jsx +69 -0
- package/src/internals/BranchesDropdown/BranchesDropdown.module.css +84 -0
- package/src/internals/CommandPalette/CommandPalette.jsx +25 -19
- package/src/internals/CommandPalette/CreateArtifactForm.jsx +150 -0
- package/src/internals/CommandPalette/CreateDialog.jsx +20 -110
- package/src/internals/CommandPalette/WidgetArtifactDialog.jsx +1 -1
- package/src/internals/CommandPalette/createHelpers.js +30 -0
- package/src/internals/CreatePage/CreatePage.jsx +57 -0
- package/src/internals/CreatePage/CreatePage.module.css +34 -0
- package/src/internals/Dialog.jsx +51 -0
- package/src/internals/SimpleWorkspace/SimpleWorkspace.jsx +533 -0
- package/src/internals/SimpleWorkspace/SimpleWorkspace.module.css +323 -0
- package/src/internals/Tooltip.jsx +39 -0
- package/src/internals/Viewfinder.jsx +196 -48
- package/src/internals/Viewfinder.module.css +72 -1
- package/src/internals/canvas/CanvasPage.jsx +267 -124
- package/src/internals/canvas/CanvasPage.multiselect.test.jsx +39 -26
- package/src/internals/canvas/PageSelector.jsx +15 -1
- package/src/internals/canvas/PageSelector.module.css +14 -0
- package/src/internals/canvas/canvasApi.js +40 -5
- package/src/internals/canvas/isolation/createIsolationMiddleware.js +68 -0
- package/src/internals/canvas/isolation/mountIsolationApp.jsx +88 -0
- package/src/internals/canvas/isolation/prototypeRoutes.jsx +131 -0
- package/src/internals/canvas/isolation/prototypesEntry.jsx +28 -0
- package/src/internals/canvas/isolation/storiesEntry.jsx +20 -0
- package/src/internals/canvas/isolation/storyRoutes.jsx +55 -0
- package/src/internals/canvas/useUndoRedo.js +75 -60
- package/src/internals/canvas/useUndoRedo.test.js +46 -178
- package/src/internals/canvas/widgets/ExpandedPaneTopBar.jsx +1 -1
- package/src/internals/canvas/widgets/FrozenTerminalOverlay.jsx +30 -21
- package/src/internals/canvas/widgets/ImageWidget.jsx +7 -2
- package/src/internals/canvas/widgets/LinkPreview.jsx +45 -1
- package/src/internals/canvas/widgets/LinkPreview.module.css +71 -0
- package/src/internals/canvas/widgets/PrototypeEmbed.jsx +69 -10
- package/src/internals/canvas/widgets/PrototypeEmbed.test.jsx +114 -0
- package/src/internals/canvas/widgets/StorySetWidget.jsx +8 -4
- package/src/internals/canvas/widgets/StoryWidget.jsx +21 -38
- package/src/internals/canvas/widgets/TerminalReadWidget.jsx +13 -15
- package/src/internals/canvas/widgets/WidgetChrome.jsx +1 -1
- package/src/internals/canvas/widgets/WidgetChrome.module.css +15 -0
- package/src/internals/canvas/widgets/embedTheme.js +2 -2
- package/src/internals/canvas/widgets/expandUtils.js +19 -19
- package/src/internals/canvas/widgets/normalizeLegacyEmbedSrc.js +74 -0
- package/src/internals/context.jsx +22 -1
- package/src/internals/context.test.jsx +47 -0
- package/src/internals/hooks/useArtifactIndex.js +31 -0
- package/src/internals/hooks/useArtifactIndex.test.js +45 -0
- package/src/internals/hooks/usePrototypeReloadGuard.js +14 -8
- package/src/internals/index.js +6 -0
- package/src/internals/loadConsumerWrapper.js +60 -0
- package/src/internals/story/ComponentSetPage.jsx +75 -34
- package/src/internals/story/StoryPage.jsx +16 -25
- package/src/internals/vite/data-plugin.js +313 -148
- package/src/internals/vite/data-plugin.test.js +11 -11
- package/{scaffold/storyboard.config.json → storyboard.config.json} +25 -0
- package/terminal.config.json +1 -1
- package/src/core/lib/components/ui/card/card-action.jsx +0 -11
- package/src/core/lib/components/ui/card/card-content.jsx +0 -11
- package/src/core/lib/components/ui/card/card-description.jsx +0 -11
- package/src/core/lib/components/ui/card/card-footer.jsx +0 -11
- package/src/core/lib/components/ui/card/card-header.jsx +0 -19
- package/src/core/lib/components/ui/card/card-title.jsx +0 -11
- package/src/core/lib/components/ui/card/card.jsx +0 -17
- package/src/core/lib/components/ui/card/index.js +0 -25
- package/src/core/lib/components/ui/collapsible/collapsible-content.jsx +0 -7
- package/src/core/lib/components/ui/collapsible/collapsible-trigger.jsx +0 -7
- package/src/core/lib/components/ui/collapsible/collapsible.jsx +0 -7
- package/src/core/lib/components/ui/collapsible/index.js +0 -13
- package/src/core/lib/components/ui/dialog/dialog-close.jsx +0 -7
- package/src/core/lib/components/ui/dialog/dialog-description.jsx +0 -15
- package/src/core/lib/components/ui/dialog/dialog-footer.jsx +0 -23
- package/src/core/lib/components/ui/dialog/dialog-header.jsx +0 -11
- package/src/core/lib/components/ui/dialog/dialog-overlay.jsx +0 -15
- package/src/core/lib/components/ui/dialog/dialog-portal.jsx +0 -4
- package/src/core/lib/components/ui/dialog/dialog-title.jsx +0 -15
- package/src/core/lib/components/ui/popover/index.js +0 -28
- package/src/core/lib/components/ui/popover/popover-close.jsx +0 -7
- package/src/core/lib/components/ui/popover/popover-content.jsx +0 -22
- package/src/core/lib/components/ui/popover/popover-description.jsx +0 -11
- package/src/core/lib/components/ui/popover/popover-header.jsx +0 -11
- package/src/core/lib/components/ui/popover/popover-portal.jsx +0 -4
- package/src/core/lib/components/ui/popover/popover-title.jsx +0 -11
- package/src/core/lib/components/ui/popover/popover-trigger.jsx +0 -8
- package/src/core/lib/components/ui/popover/popover.jsx +0 -4
- package/src/core/lib/components/ui/select/index.js +0 -37
- package/src/core/lib/components/ui/select/select-content.jsx +0 -30
- package/src/core/lib/components/ui/select/select-group-heading.jsx +0 -17
- package/src/core/lib/components/ui/select/select-group.jsx +0 -15
- package/src/core/lib/components/ui/select/select-item.jsx +0 -26
- package/src/core/lib/components/ui/select/select-label.jsx +0 -11
- package/src/core/lib/components/ui/select/select-portal.jsx +0 -4
- package/src/core/lib/components/ui/select/select-scroll-down-button.jsx +0 -18
- package/src/core/lib/components/ui/select/select-scroll-up-button.jsx +0 -18
- package/src/core/lib/components/ui/select/select-separator.jsx +0 -15
- package/src/core/lib/components/ui/select/select-trigger.jsx +0 -25
- package/src/core/lib/components/ui/select/select.jsx +0 -4
- package/src/core/lib/components/ui/sheet/index.js +0 -34
- package/src/core/lib/components/ui/sheet/sheet-close.jsx +0 -7
- package/src/core/lib/components/ui/sheet/sheet-content.jsx +0 -35
- package/src/core/lib/components/ui/sheet/sheet-description.jsx +0 -15
- package/src/core/lib/components/ui/sheet/sheet-footer.jsx +0 -11
- package/src/core/lib/components/ui/sheet/sheet-header.jsx +0 -11
- package/src/core/lib/components/ui/sheet/sheet-overlay.jsx +0 -15
- package/src/core/lib/components/ui/sheet/sheet-portal.jsx +0 -4
- package/src/core/lib/components/ui/sheet/sheet-title.jsx +0 -15
- package/src/core/lib/components/ui/sheet/sheet-trigger.jsx +0 -7
- package/src/core/lib/components/ui/sheet/sheet.jsx +0 -4
- package/src/core/lib/components/ui/toggle/index.js +0 -8
- package/src/core/lib/components/ui/toggle/toggle.jsx +0 -36
- package/src/core/lib/components/ui/toggle-group/index.js +0 -10
- package/src/core/lib/components/ui/toggle-group/toggle-group-item.jsx +0 -29
- package/src/core/lib/components/ui/toggle-group/toggle-group.jsx +0 -43
- package/src/internals/canvas/StoryErrorBoundary.jsx +0 -47
- package/src/internals/canvas/componentIsolate.jsx +0 -144
- package/src/internals/canvas/componentSetIsolate.jsx +0 -300
- package/src/internals/canvas/widgets/InlineStoryRenderer.jsx +0 -129
- package/src/internals/canvas/widgets/InlineStoryRenderer.test.jsx +0 -68
- package/src/primer/ThemeSync.jsx +0 -73
- package/src/primer/index.js +0 -1
|
@@ -5,12 +5,25 @@
|
|
|
5
5
|
* Formerly known as Viewfinder — renamed to match the /workspace route.
|
|
6
6
|
*/
|
|
7
7
|
import { useState, useEffect, useRef, useMemo, useCallback, useSyncExternalStore } from 'react'
|
|
8
|
-
import {
|
|
9
|
-
|
|
8
|
+
import {
|
|
9
|
+
buildPrototypeIndex,
|
|
10
|
+
listStories,
|
|
11
|
+
getStoryData,
|
|
12
|
+
BranchSelect,
|
|
13
|
+
getCustomerModeConfig,
|
|
14
|
+
trackRecent,
|
|
15
|
+
subscribeToRecent,
|
|
16
|
+
getRecentSnapshot,
|
|
17
|
+
} from '../core/index.js'
|
|
18
|
+
import { buildBranchArtifactHref, mergeArtifactIndexIntoPrototypeIndex } from '../core/data/artifactIndex.js'
|
|
19
|
+
import { MarkGithubIcon, GitBranchIcon, ChevronDownIcon, ChevronRightIcon, PlusIcon, StarIcon, StarFillIcon, ThreeBarsIcon, XIcon, StackIcon, TrashIcon, ShieldLockIcon, KebabHorizontalIcon, PencilIcon, EyeClosedIcon } from '@primer/octicons-react'
|
|
10
20
|
import { Menu } from '@base-ui/react/menu'
|
|
11
21
|
import { Dialog } from '@base-ui/react/dialog'
|
|
22
|
+
import Tooltip from './Tooltip.jsx'
|
|
12
23
|
import Icon from './Icon.jsx'
|
|
13
24
|
import { useBranches } from './BranchBar/useBranches.js'
|
|
25
|
+
import { useArtifactIndex } from './hooks/useArtifactIndex.js'
|
|
26
|
+
import BranchesDropdown from './BranchesDropdown/BranchesDropdown.jsx'
|
|
14
27
|
import css from './Viewfinder.module.css'
|
|
15
28
|
|
|
16
29
|
/* ─── Theme sync: read toolbar theme from DOM and apply to Primer/BaseUI ─── */
|
|
@@ -96,8 +109,6 @@ function useGitHubUser() {
|
|
|
96
109
|
/* ─── localStorage helpers ─── */
|
|
97
110
|
|
|
98
111
|
const STARRED_KEY = 'sb-workspace-starred'
|
|
99
|
-
const RECENT_KEY = 'sb-workspace-recent'
|
|
100
|
-
const MAX_RECENT = 30
|
|
101
112
|
const GROUP_BY_FOLDERS_KEY = 'sb-workspace-group-folders'
|
|
102
113
|
const COLLAPSED_FOLDERS_KEY = 'sb-workspace-collapsed-folders'
|
|
103
114
|
|
|
@@ -122,7 +133,6 @@ function createLocalStorageStore(key, fallback) {
|
|
|
122
133
|
}
|
|
123
134
|
|
|
124
135
|
const starredStore = createLocalStorageStore(STARRED_KEY, [])
|
|
125
|
-
const recentStore = createLocalStorageStore(RECENT_KEY, [])
|
|
126
136
|
|
|
127
137
|
function useStarred() {
|
|
128
138
|
const raw = useSyncExternalStore(starredStore.subscribe, starredStore.getSnapshot)
|
|
@@ -135,15 +145,61 @@ function useStarred() {
|
|
|
135
145
|
return { starred: new Set(ids), toggle }
|
|
136
146
|
}
|
|
137
147
|
|
|
148
|
+
/**
|
|
149
|
+
* Map a recent store entry `{type, key}` to the composite id used by the
|
|
150
|
+
* workspace `itemMap` (`proto:`, `canvas:`, `component:`).
|
|
151
|
+
*
|
|
152
|
+
* The unified recent store uses `'story'` as the canonical type for
|
|
153
|
+
* component/story artifacts (matches `core/stores/paletteProviders.js`),
|
|
154
|
+
* but the workspace's items use `'component'` for the same things.
|
|
155
|
+
*/
|
|
156
|
+
function recentEntryToItemId(entry) {
|
|
157
|
+
if (!entry || typeof entry.type !== 'string' || typeof entry.key !== 'string') return null
|
|
158
|
+
switch (entry.type) {
|
|
159
|
+
case 'prototype': return `proto:${entry.key}`
|
|
160
|
+
case 'canvas': return `canvas:${entry.key}`
|
|
161
|
+
case 'story':
|
|
162
|
+
case 'component': return `component:${entry.key}`
|
|
163
|
+
default: return `${entry.type}:${entry.key}`
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
/**
|
|
168
|
+
* Map a workspace `item.type` value to the canonical type stored in the
|
|
169
|
+
* recent artifacts store. The workspace uses `'component'` for stories
|
|
170
|
+
* but the recent store (shared with the command palette) uses `'story'`.
|
|
171
|
+
*/
|
|
172
|
+
function itemTypeToRecentType(itemType) {
|
|
173
|
+
if (itemType === 'component') return 'story'
|
|
174
|
+
return itemType
|
|
175
|
+
}
|
|
176
|
+
|
|
138
177
|
function useRecent() {
|
|
139
|
-
const raw = useSyncExternalStore(
|
|
140
|
-
return
|
|
178
|
+
const raw = useSyncExternalStore(subscribeToRecent, getRecentSnapshot)
|
|
179
|
+
return useMemo(() => {
|
|
180
|
+
try {
|
|
181
|
+
const entries = JSON.parse(raw)
|
|
182
|
+
if (!Array.isArray(entries)) return []
|
|
183
|
+
const ids = []
|
|
184
|
+
for (const entry of entries) {
|
|
185
|
+
const id = recentEntryToItemId(entry)
|
|
186
|
+
if (id) ids.push(id)
|
|
187
|
+
}
|
|
188
|
+
return ids
|
|
189
|
+
} catch {
|
|
190
|
+
return []
|
|
191
|
+
}
|
|
192
|
+
}, [raw])
|
|
141
193
|
}
|
|
142
194
|
|
|
143
|
-
function
|
|
144
|
-
|
|
145
|
-
const
|
|
146
|
-
|
|
195
|
+
function trackRecentItem(item) {
|
|
196
|
+
if (!item || !item.id) return
|
|
197
|
+
const colonIdx = item.id.indexOf(':')
|
|
198
|
+
if (colonIdx <= 0) return
|
|
199
|
+
const key = item.id.slice(colonIdx + 1)
|
|
200
|
+
const type = itemTypeToRecentType(item.type)
|
|
201
|
+
if (!type) return
|
|
202
|
+
trackRecent(type, key, item.name || key)
|
|
147
203
|
}
|
|
148
204
|
|
|
149
205
|
/* ─── URL helpers ─── */
|
|
@@ -440,18 +496,26 @@ function DeleteArtifactModal({ item, dirName, basePath, typeLabel, onClose, onDe
|
|
|
440
496
|
|
|
441
497
|
/* ─── Artifact Card ─── */
|
|
442
498
|
|
|
443
|
-
function ArtifactCard({ item, basePath, starred, onToggleStar, onItemDeleted }) {
|
|
444
|
-
const
|
|
499
|
+
function ArtifactCard({ item, basePath, branchBasePath, currentBranch, starred, onToggleStar, onItemDeleted }) {
|
|
500
|
+
const isBranchOnly = !!item.isBranchOnly
|
|
445
501
|
const isExternal = item.isExternal
|
|
502
|
+
const branchOnlyHref = isBranchOnly
|
|
503
|
+
? isExternal
|
|
504
|
+
? item.externalUrl
|
|
505
|
+
: buildBranchArtifactHref(branchBasePath || basePath, item.homeBranch?.folder, item.homeBranch?.route || item.route)
|
|
506
|
+
: null
|
|
507
|
+
const href = item.route ? withBase(basePath, item.route) : '#'
|
|
446
508
|
|
|
447
509
|
const handleClick = () => {
|
|
448
|
-
|
|
510
|
+
if (!isBranchOnly) trackRecentItem(item)
|
|
449
511
|
}
|
|
450
512
|
|
|
451
|
-
const Tag =
|
|
452
|
-
const linkProps =
|
|
453
|
-
? { href:
|
|
454
|
-
:
|
|
513
|
+
const Tag = 'a'
|
|
514
|
+
const linkProps = isBranchOnly
|
|
515
|
+
? { href: branchOnlyHref || '#', target: '_blank', rel: 'noopener noreferrer' }
|
|
516
|
+
: isExternal
|
|
517
|
+
? { href: item.externalUrl, target: '_blank', rel: 'noopener noreferrer' }
|
|
518
|
+
: { href }
|
|
455
519
|
|
|
456
520
|
const authorList = item.author
|
|
457
521
|
? (Array.isArray(item.author) ? item.author : [item.author])
|
|
@@ -463,17 +527,40 @@ function ArtifactCard({ item, basePath, starred, onToggleStar, onItemDeleted })
|
|
|
463
527
|
// Extract dirName from item.id (format: "type:dirName")
|
|
464
528
|
const dirName = item.id.split(':').slice(1).join(':')
|
|
465
529
|
const typeLabel = item.type === 'canvas' ? 'Canvas' : item.type === 'prototype' ? 'Prototype' : 'Component'
|
|
466
|
-
const canEditDelete = item.type === 'canvas' || item.type === 'prototype'
|
|
530
|
+
const canEditDelete = !isBranchOnly && (item.type === 'canvas' || item.type === 'prototype')
|
|
531
|
+
const cardClass = `${css.card}${item.isPrivate ? ' ' + css.cardPrivate : ''}${isBranchOnly ? ' ' + css.branchOnlyCard : ''}`
|
|
467
532
|
|
|
468
533
|
return (
|
|
469
534
|
<>
|
|
470
|
-
<Tag className={
|
|
535
|
+
<Tag className={cardClass} {...linkProps} onClick={handleClick}>
|
|
471
536
|
<div className={css.cardHeader}>
|
|
472
|
-
<
|
|
537
|
+
<div className={css.cardBadgeGroup}>
|
|
538
|
+
<span className={css.cardBadge}>{getTypeLabel(item.type)}</span>
|
|
539
|
+
{isBranchOnly && <span className={css.branchOnlyBadge}>Branch-only</span>}
|
|
540
|
+
{item.isPrivate && !isBranchOnly && (
|
|
541
|
+
<Tooltip text={`${typeLabel} not published, only visible to you`} direction="n">
|
|
542
|
+
<button
|
|
543
|
+
type="button"
|
|
544
|
+
className={css.cardPrivateBadge}
|
|
545
|
+
aria-label={`Private ${typeLabel.toLowerCase()}`}
|
|
546
|
+
onClick={(e) => { e.preventDefault(); e.stopPropagation() }}
|
|
547
|
+
>
|
|
548
|
+
<EyeClosedIcon size={12} />
|
|
549
|
+
</button>
|
|
550
|
+
</Tooltip>
|
|
551
|
+
)}
|
|
552
|
+
</div>
|
|
473
553
|
<div className={css.cardActions}>
|
|
474
|
-
<StarBtn active={starred} onClick={() => onToggleStar(item.id)} inline />
|
|
475
|
-
{item.flows?.length > 1 && <FlowsDropdown flows={item.flows} basePath={basePath} />}
|
|
476
|
-
{item.pages?.length > 1 && <PagesDropdown pages={item.pages} basePath={basePath} />}
|
|
554
|
+
{!isBranchOnly && <StarBtn active={starred} onClick={() => onToggleStar(item.id)} inline />}
|
|
555
|
+
{!isBranchOnly && item.flows?.length > 1 && <FlowsDropdown flows={item.flows} basePath={basePath} />}
|
|
556
|
+
{!isBranchOnly && item.pages?.length > 1 && <PagesDropdown pages={item.pages} basePath={basePath} />}
|
|
557
|
+
<BranchesDropdown
|
|
558
|
+
branches={item.branches || []}
|
|
559
|
+
branchBasePath={branchBasePath}
|
|
560
|
+
currentBranch={currentBranch}
|
|
561
|
+
homeTitle={item.name}
|
|
562
|
+
homeFolder={item.folder}
|
|
563
|
+
/>
|
|
477
564
|
{canEditDelete && (
|
|
478
565
|
<CardActionsMenu
|
|
479
566
|
typeLabel={typeLabel}
|
|
@@ -505,7 +592,7 @@ function ArtifactCard({ item, basePath, starred, onToggleStar, onItemDeleted })
|
|
|
505
592
|
</div>
|
|
506
593
|
</div>
|
|
507
594
|
</Tag>
|
|
508
|
-
{showEdit && (
|
|
595
|
+
{showEdit && !isBranchOnly && (
|
|
509
596
|
<EditArtifactModal
|
|
510
597
|
item={item}
|
|
511
598
|
dirName={dirName}
|
|
@@ -513,7 +600,7 @@ function ArtifactCard({ item, basePath, starred, onToggleStar, onItemDeleted })
|
|
|
513
600
|
onClose={() => setShowEdit(false)}
|
|
514
601
|
/>
|
|
515
602
|
)}
|
|
516
|
-
{showDelete && (
|
|
603
|
+
{showDelete && !isBranchOnly && (
|
|
517
604
|
<DeleteArtifactModal
|
|
518
605
|
item={item}
|
|
519
606
|
dirName={dirName}
|
|
@@ -609,8 +696,12 @@ function PagesDropdown({ pages, basePath }) {
|
|
|
609
696
|
<a
|
|
610
697
|
href={withBase(basePath, page.route)}
|
|
611
698
|
className={css.flowsItemLink}
|
|
699
|
+
title={page.isPrivate ? 'Local-only page — gitignored, dev-only' : undefined}
|
|
612
700
|
>
|
|
613
701
|
{page.name}
|
|
702
|
+
{page.isPrivate && (
|
|
703
|
+
<EyeClosedIcon size={12} className={css.flowsItemPrivateIcon} />
|
|
704
|
+
)}
|
|
614
705
|
</a>
|
|
615
706
|
</Menu.Item>
|
|
616
707
|
))}
|
|
@@ -623,18 +714,37 @@ function PagesDropdown({ pages, basePath }) {
|
|
|
623
714
|
|
|
624
715
|
/* ─── Folder Section ─── */
|
|
625
716
|
|
|
626
|
-
function FolderSection({ folder, collapsed, onToggle, basePath, starred, onToggleStar, onItemDeleted }) {
|
|
717
|
+
function FolderSection({ folder, collapsed, onToggle, basePath, branchBasePath, currentBranch, starred, onToggleStar, onItemDeleted }) {
|
|
718
|
+
const sectionClass = collapsed ? css.folderSectionCollapsed : css.folderSection
|
|
627
719
|
return (
|
|
628
|
-
<section className={
|
|
629
|
-
<
|
|
720
|
+
<section className={`${sectionClass}${folder.isPrivate ? ' ' + css.folderSectionPrivate : ''}`}>
|
|
721
|
+
<div
|
|
722
|
+
className={css.folderHeader}
|
|
723
|
+
role="button"
|
|
724
|
+
tabIndex={0}
|
|
725
|
+
onClick={onToggle}
|
|
726
|
+
onKeyDown={(e) => { if (e.key === 'Enter' || e.key === ' ') { e.preventDefault(); onToggle() } }}
|
|
727
|
+
>
|
|
630
728
|
<Icon name={collapsed ? 'folder' : 'folder-open'} size={16} className={css.folderIcon} />
|
|
631
729
|
<span className={css.folderName}>{folder.name}</span>
|
|
730
|
+
{folder.isPrivate && (
|
|
731
|
+
<Tooltip text="Folder not published, only visible to you" direction="n">
|
|
732
|
+
<button
|
|
733
|
+
type="button"
|
|
734
|
+
className={css.folderPrivateBadge}
|
|
735
|
+
aria-label="Private folder"
|
|
736
|
+
onClick={(e) => { e.preventDefault(); e.stopPropagation() }}
|
|
737
|
+
>
|
|
738
|
+
<EyeClosedIcon size={12} />
|
|
739
|
+
</button>
|
|
740
|
+
</Tooltip>
|
|
741
|
+
)}
|
|
632
742
|
<span className={css.folderCount}>{folder.items.length}</span>
|
|
633
743
|
<ChevronRightIcon
|
|
634
744
|
size={14}
|
|
635
745
|
className={collapsed ? css.folderChevron : css.folderChevronExpanded}
|
|
636
746
|
/>
|
|
637
|
-
</
|
|
747
|
+
</div>
|
|
638
748
|
{!collapsed && (
|
|
639
749
|
<div className={css.grid}>
|
|
640
750
|
{folder.items.map(item => (
|
|
@@ -642,6 +752,8 @@ function FolderSection({ folder, collapsed, onToggle, basePath, starred, onToggl
|
|
|
642
752
|
key={item.id}
|
|
643
753
|
item={item}
|
|
644
754
|
basePath={basePath}
|
|
755
|
+
branchBasePath={branchBasePath}
|
|
756
|
+
currentBranch={currentBranch}
|
|
645
757
|
starred={starred.has(item.id)}
|
|
646
758
|
onToggleStar={onToggleStar}
|
|
647
759
|
onItemDeleted={onItemDeleted}
|
|
@@ -878,7 +990,7 @@ function CreateForm({ type, onClose, basePath }) {
|
|
|
878
990
|
|
|
879
991
|
/* ─── Create Menu (Dropdown) ─── */
|
|
880
992
|
|
|
881
|
-
function CreateMenu({ onClose, basePath }) {
|
|
993
|
+
export function CreateMenu({ onClose, basePath }) {
|
|
882
994
|
const [activeForm, setActiveForm] = useState(null)
|
|
883
995
|
const [showMore, setShowMore] = useState(false)
|
|
884
996
|
|
|
@@ -956,6 +1068,7 @@ const NAV_ITEMS = [
|
|
|
956
1068
|
]
|
|
957
1069
|
|
|
958
1070
|
const TAB_FILTERS = ['All', 'Recent', 'Starred']
|
|
1071
|
+
const TYPE_MAP = { prototypes: 'prototype', canvases: 'canvas', components: 'component' }
|
|
959
1072
|
|
|
960
1073
|
/* ─── Branch Navigation ─── */
|
|
961
1074
|
|
|
@@ -970,7 +1083,17 @@ function BranchNav({ basePath }) {
|
|
|
970
1083
|
if (isLocalDev) return null
|
|
971
1084
|
if (!branches || branches.length === 0) return null
|
|
972
1085
|
|
|
973
|
-
|
|
1086
|
+
// Ensure `main` is always present and sorted first. CI's `branches.json`
|
|
1087
|
+
// historically lists only `branch--*/` folders, so `main` is missing on
|
|
1088
|
+
// prod deploys — without this the <select> falls back to its first option
|
|
1089
|
+
// (often something like `0.5.0-fix-…`) when the user is actually on main.
|
|
1090
|
+
const branchNames = [
|
|
1091
|
+
'main',
|
|
1092
|
+
...branches
|
|
1093
|
+
.map(b => b.branch)
|
|
1094
|
+
.filter(b => b && b !== 'main')
|
|
1095
|
+
.sort((a, b) => a.localeCompare(b)),
|
|
1096
|
+
]
|
|
974
1097
|
|
|
975
1098
|
const navigate = async (branch) => {
|
|
976
1099
|
if (switching) return
|
|
@@ -1093,6 +1216,8 @@ function WorkspaceImpl({
|
|
|
1093
1216
|
basePath,
|
|
1094
1217
|
title = 'Storyboard',
|
|
1095
1218
|
subtitle,
|
|
1219
|
+
logo,
|
|
1220
|
+
logoIcon = 'iconoir/key-command',
|
|
1096
1221
|
showAllArtifacts = false,
|
|
1097
1222
|
showPrototypes = true,
|
|
1098
1223
|
showCanvases = true,
|
|
@@ -1100,6 +1225,8 @@ function WorkspaceImpl({
|
|
|
1100
1225
|
}) {
|
|
1101
1226
|
const themeAttrs = useToolbarTheme()
|
|
1102
1227
|
const ghUser = useGitHubUser(basePath)
|
|
1228
|
+
const { currentBranch, branchBasePath } = useBranches(basePath)
|
|
1229
|
+
const { artifactIndex } = useArtifactIndex(basePath)
|
|
1103
1230
|
const [settingsOpen, setSettingsOpen] = useState(false)
|
|
1104
1231
|
|
|
1105
1232
|
const handleRemoveToken = useCallback(() => {
|
|
@@ -1129,13 +1256,17 @@ function WorkspaceImpl({
|
|
|
1129
1256
|
const knownRoutes = useMemo(() =>
|
|
1130
1257
|
Object.keys(pageModules)
|
|
1131
1258
|
.map(p => p.replace('/src/prototypes/', '').replace('.jsx', ''))
|
|
1132
|
-
.filter(n => !n.startsWith('_') && n !== 'index' && n !== 'workspace' && n !== 'viewfinder'),
|
|
1259
|
+
.filter(n => !n.startsWith('_') && n !== 'index' && n !== 'workspace' && n !== 'viewfinder' && n !== 'create'),
|
|
1133
1260
|
[pageModules],
|
|
1134
1261
|
)
|
|
1135
1262
|
|
|
1136
1263
|
// canvasIndexTick is an intentional re-render trigger from HMR events
|
|
1137
1264
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
1138
|
-
const
|
|
1265
|
+
const localPrototypeIndex = useMemo(() => buildPrototypeIndex(knownRoutes), [knownRoutes, canvasIndexTick])
|
|
1266
|
+
const prototypeIndex = useMemo(
|
|
1267
|
+
() => mergeArtifactIndexIntoPrototypeIndex(localPrototypeIndex, artifactIndex, currentBranch),
|
|
1268
|
+
[localPrototypeIndex, artifactIndex, currentBranch],
|
|
1269
|
+
)
|
|
1139
1270
|
|
|
1140
1271
|
// Build unified items list from all sources
|
|
1141
1272
|
const allItems = useMemo(() => {
|
|
@@ -1152,18 +1283,22 @@ function WorkspaceImpl({
|
|
|
1152
1283
|
: `/${proto.dirName}`
|
|
1153
1284
|
|
|
1154
1285
|
items.push({
|
|
1155
|
-
id: `proto:${proto.dirName}`,
|
|
1286
|
+
id: proto.id || `proto:${proto.dirName}`,
|
|
1156
1287
|
name: proto.name,
|
|
1157
1288
|
type: 'prototype',
|
|
1158
1289
|
author: proto.author,
|
|
1159
1290
|
gitAuthor: proto.gitAuthor,
|
|
1160
1291
|
lastModified: proto.lastModified,
|
|
1161
|
-
route,
|
|
1292
|
+
route: proto.route || route,
|
|
1162
1293
|
isExternal: proto.isExternal,
|
|
1163
1294
|
externalUrl: proto.externalUrl,
|
|
1164
1295
|
folder: proto.folder,
|
|
1165
1296
|
description: proto.description,
|
|
1166
1297
|
flows: proto.flows || [],
|
|
1298
|
+
isPrivate: !!proto.isPrivate,
|
|
1299
|
+
branches: proto.branches || [],
|
|
1300
|
+
isBranchOnly: !!proto.isBranchOnly,
|
|
1301
|
+
homeBranch: proto.homeBranch || null,
|
|
1167
1302
|
})
|
|
1168
1303
|
}
|
|
1169
1304
|
|
|
@@ -1175,18 +1310,22 @@ function WorkspaceImpl({
|
|
|
1175
1310
|
// Canvases (ungrouped + from folders)
|
|
1176
1311
|
const addCanvas = (canvas) => {
|
|
1177
1312
|
items.push({
|
|
1178
|
-
id: `canvas:${canvas.dirName}`,
|
|
1313
|
+
id: canvas.id || `canvas:${canvas.dirName}`,
|
|
1179
1314
|
name: canvas.name,
|
|
1180
1315
|
type: 'canvas',
|
|
1181
1316
|
author: canvas.author,
|
|
1182
1317
|
gitAuthor: canvas.gitAuthor,
|
|
1183
|
-
lastModified: null,
|
|
1318
|
+
lastModified: canvas.lastModified || null,
|
|
1184
1319
|
route: canvas.route,
|
|
1185
1320
|
isExternal: false,
|
|
1186
1321
|
externalUrl: null,
|
|
1187
1322
|
folder: canvas.folder,
|
|
1188
1323
|
description: canvas.description,
|
|
1189
1324
|
pages: canvas.pages || null,
|
|
1325
|
+
isPrivate: !!canvas.isPrivate,
|
|
1326
|
+
branches: canvas.branches || [],
|
|
1327
|
+
isBranchOnly: !!canvas.isBranchOnly,
|
|
1328
|
+
homeBranch: canvas.homeBranch || null,
|
|
1190
1329
|
})
|
|
1191
1330
|
}
|
|
1192
1331
|
|
|
@@ -1200,9 +1339,10 @@ function WorkspaceImpl({
|
|
|
1200
1339
|
for (const name of storyNames) {
|
|
1201
1340
|
const data = getStoryData(name)
|
|
1202
1341
|
if (!data) continue
|
|
1342
|
+
const displayName = (name.split('/').pop() || name).replace(/^~/, '')
|
|
1203
1343
|
items.push({
|
|
1204
1344
|
id: `component:${name}`,
|
|
1205
|
-
name:
|
|
1345
|
+
name: displayName.split('-').map(w => w.charAt(0).toUpperCase() + w.slice(1)).join(' '),
|
|
1206
1346
|
type: 'component',
|
|
1207
1347
|
author: null,
|
|
1208
1348
|
gitAuthor: null,
|
|
@@ -1212,6 +1352,7 @@ function WorkspaceImpl({
|
|
|
1212
1352
|
externalUrl: null,
|
|
1213
1353
|
folder: null,
|
|
1214
1354
|
description: null,
|
|
1355
|
+
isPrivate: !!data._isPrivate || name.split('/').includes('drafts'),
|
|
1215
1356
|
})
|
|
1216
1357
|
}
|
|
1217
1358
|
|
|
@@ -1253,9 +1394,8 @@ function WorkspaceImpl({
|
|
|
1253
1394
|
const recentIds = useRecent()
|
|
1254
1395
|
|
|
1255
1396
|
// Filter by nav category
|
|
1256
|
-
const typeMap = { prototypes: 'prototype', canvases: 'canvas', components: 'component' }
|
|
1257
1397
|
const navFiltered = useMemo(() => {
|
|
1258
|
-
let filtered = activeNav === 'all' ? allItems : allItems.filter(i => i.type ===
|
|
1398
|
+
let filtered = activeNav === 'all' ? allItems : allItems.filter(i => i.type === TYPE_MAP[activeNav])
|
|
1259
1399
|
if (hiddenItems.size > 0) filtered = filtered.filter(i => !hiddenItems.has(i.id))
|
|
1260
1400
|
return filtered
|
|
1261
1401
|
}, [allItems, activeNav, hiddenItems])
|
|
@@ -1263,15 +1403,14 @@ function WorkspaceImpl({
|
|
|
1263
1403
|
// Filter by tab
|
|
1264
1404
|
const items = useMemo(() => {
|
|
1265
1405
|
if (activeTab === 'Recent') {
|
|
1266
|
-
const ordered = recentIds.map(id => itemMap[id]).filter(
|
|
1406
|
+
const ordered = recentIds.map(id => itemMap[id]).filter(item => item && !item.isBranchOnly)
|
|
1267
1407
|
if (activeNav !== 'all') {
|
|
1268
|
-
|
|
1269
|
-
return ordered.filter(i => i.type === typeMap[activeNav])
|
|
1408
|
+
return ordered.filter(i => i.type === TYPE_MAP[activeNav])
|
|
1270
1409
|
}
|
|
1271
1410
|
return ordered
|
|
1272
1411
|
}
|
|
1273
1412
|
const base = activeTab === 'Starred'
|
|
1274
|
-
? navFiltered.filter(i => starred.has(i.id))
|
|
1413
|
+
? navFiltered.filter(i => !i.isBranchOnly && starred.has(i.id))
|
|
1275
1414
|
: navFiltered
|
|
1276
1415
|
return [...base].sort((a, b) => {
|
|
1277
1416
|
const aTime = a.lastModified ? new Date(a.lastModified).getTime() : 0
|
|
@@ -1298,6 +1437,7 @@ function WorkspaceImpl({
|
|
|
1298
1437
|
const folders = Object.entries(folderItems).map(([dirName, fItems]) => ({
|
|
1299
1438
|
dirName,
|
|
1300
1439
|
name: folderMeta[dirName]?.name || dirName,
|
|
1440
|
+
isPrivate: !!folderMeta[dirName]?.isPrivate || dirName === 'drafts',
|
|
1301
1441
|
items: fItems,
|
|
1302
1442
|
}))
|
|
1303
1443
|
folders.sort((a, b) => {
|
|
@@ -1343,7 +1483,7 @@ function WorkspaceImpl({
|
|
|
1343
1483
|
}), [visibleItems])
|
|
1344
1484
|
|
|
1345
1485
|
// Starred items for sidebar
|
|
1346
|
-
const starredItems = useMemo(() => visibleItems.filter(i => starred.has(i.id)), [visibleItems, starred])
|
|
1486
|
+
const starredItems = useMemo(() => visibleItems.filter(i => !i.isBranchOnly && starred.has(i.id)), [visibleItems, starred])
|
|
1347
1487
|
|
|
1348
1488
|
return (
|
|
1349
1489
|
<div className={css.layout} {...themeAttrs}>
|
|
@@ -1357,7 +1497,9 @@ function WorkspaceImpl({
|
|
|
1357
1497
|
>
|
|
1358
1498
|
{sidebarOpen ? <XIcon size={18} /> : <ThreeBarsIcon size={18} />}
|
|
1359
1499
|
</button>
|
|
1360
|
-
|
|
1500
|
+
{logo
|
|
1501
|
+
? <div className={`${css.logo} smooth-corners`}>{logo}</div>
|
|
1502
|
+
: <div className={`${css.logo} smooth-corners`}><Icon name={logoIcon} size={22} color="#fff" /></div>}
|
|
1361
1503
|
<div>
|
|
1362
1504
|
<div className={css.appName}>{title}</div>
|
|
1363
1505
|
{subtitle && <div className={css.appSubtitle}>{subtitle}</div>}
|
|
@@ -1413,7 +1555,7 @@ function WorkspaceImpl({
|
|
|
1413
1555
|
className={css.starredItem}
|
|
1414
1556
|
href={s.isExternal ? s.externalUrl : withBase(basePath, s.route)}
|
|
1415
1557
|
{...(s.isExternal ? { target: '_blank', rel: 'noopener noreferrer' } : {})}
|
|
1416
|
-
onClick={() =>
|
|
1558
|
+
onClick={() => trackRecentItem(s)}
|
|
1417
1559
|
>
|
|
1418
1560
|
<span className={css.starredIcon}>{getTypeIcon(s.type)}</span>
|
|
1419
1561
|
{s.name}
|
|
@@ -1499,6 +1641,8 @@ function WorkspaceImpl({
|
|
|
1499
1641
|
collapsed={collapsedFolders.has(folder.dirName)}
|
|
1500
1642
|
onToggle={() => toggleFolder(folder.dirName)}
|
|
1501
1643
|
basePath={basePath}
|
|
1644
|
+
branchBasePath={branchBasePath}
|
|
1645
|
+
currentBranch={currentBranch}
|
|
1502
1646
|
starred={starred}
|
|
1503
1647
|
onToggleStar={toggleStar}
|
|
1504
1648
|
onItemDeleted={handleItemDeleted}
|
|
@@ -1511,6 +1655,8 @@ function WorkspaceImpl({
|
|
|
1511
1655
|
key={item.id}
|
|
1512
1656
|
item={item}
|
|
1513
1657
|
basePath={basePath}
|
|
1658
|
+
branchBasePath={branchBasePath}
|
|
1659
|
+
currentBranch={currentBranch}
|
|
1514
1660
|
starred={starred.has(item.id)}
|
|
1515
1661
|
onToggleStar={toggleStar}
|
|
1516
1662
|
onItemDeleted={handleItemDeleted}
|
|
@@ -1526,6 +1672,8 @@ function WorkspaceImpl({
|
|
|
1526
1672
|
key={item.id}
|
|
1527
1673
|
item={item}
|
|
1528
1674
|
basePath={basePath}
|
|
1675
|
+
branchBasePath={branchBasePath}
|
|
1676
|
+
currentBranch={currentBranch}
|
|
1529
1677
|
starred={starred.has(item.id)}
|
|
1530
1678
|
onToggleStar={toggleStar}
|
|
1531
1679
|
onItemDeleted={handleItemDeleted}
|
|
@@ -642,6 +642,23 @@
|
|
|
642
642
|
color: inherit;
|
|
643
643
|
}
|
|
644
644
|
|
|
645
|
+
.cardPrivate {
|
|
646
|
+
opacity: 0.8;
|
|
647
|
+
}
|
|
648
|
+
|
|
649
|
+
.cardPrivate:hover {
|
|
650
|
+
opacity: 1;
|
|
651
|
+
}
|
|
652
|
+
|
|
653
|
+
.branchOnlyCard {
|
|
654
|
+
background: var(--bgColor-muted, #f6f8fa);
|
|
655
|
+
border-color: var(--borderColor-muted, #d8dee4);
|
|
656
|
+
}
|
|
657
|
+
|
|
658
|
+
.branchOnlyCard:hover {
|
|
659
|
+
border-color: var(--borderColor-accent-muted, #54aeff66);
|
|
660
|
+
}
|
|
661
|
+
|
|
645
662
|
.cardThumb {
|
|
646
663
|
height: 140px;
|
|
647
664
|
background: var(--bgColor-muted, #f5f5f5);
|
|
@@ -663,6 +680,33 @@
|
|
|
663
680
|
color: var(--fgColor-muted, #555);
|
|
664
681
|
}
|
|
665
682
|
|
|
683
|
+
.branchOnlyBadge {
|
|
684
|
+
padding: 3px 8px;
|
|
685
|
+
border-radius: 999px;
|
|
686
|
+
font-size: 11px;
|
|
687
|
+
font-weight: 700;
|
|
688
|
+
text-transform: uppercase;
|
|
689
|
+
letter-spacing: 0.4px;
|
|
690
|
+
background: var(--bgColor-accent-muted, #ddf4ff);
|
|
691
|
+
color: var(--fgColor-accent, #0969da);
|
|
692
|
+
}
|
|
693
|
+
|
|
694
|
+
.cardPrivateBadge {
|
|
695
|
+
display: inline-flex;
|
|
696
|
+
align-items: center;
|
|
697
|
+
justify-content: center;
|
|
698
|
+
color: var(--fgColor-muted, #656d76);
|
|
699
|
+
background: none;
|
|
700
|
+
border: none;
|
|
701
|
+
padding: 2px;
|
|
702
|
+
}
|
|
703
|
+
|
|
704
|
+
.cardBadgeGroup {
|
|
705
|
+
display: flex;
|
|
706
|
+
align-items: center;
|
|
707
|
+
gap: 6px;
|
|
708
|
+
}
|
|
709
|
+
|
|
666
710
|
/* Icon buttons (star, flows, etc.) */
|
|
667
711
|
|
|
668
712
|
.iconBtn {
|
|
@@ -1036,6 +1080,25 @@
|
|
|
1036
1080
|
flex: 1;
|
|
1037
1081
|
}
|
|
1038
1082
|
|
|
1083
|
+
.folderSectionPrivate {
|
|
1084
|
+
opacity: 0.8;
|
|
1085
|
+
}
|
|
1086
|
+
|
|
1087
|
+
.folderSectionPrivate:hover {
|
|
1088
|
+
opacity: 1;
|
|
1089
|
+
}
|
|
1090
|
+
|
|
1091
|
+
.folderPrivateBadge {
|
|
1092
|
+
display: inline-flex;
|
|
1093
|
+
align-items: center;
|
|
1094
|
+
justify-content: center;
|
|
1095
|
+
color: var(--fgColor-muted, #656d76);
|
|
1096
|
+
background: none;
|
|
1097
|
+
border: none;
|
|
1098
|
+
padding: 2px;
|
|
1099
|
+
margin-right: 6px;
|
|
1100
|
+
}
|
|
1101
|
+
|
|
1039
1102
|
.folderCount {
|
|
1040
1103
|
font-size: 14px;
|
|
1041
1104
|
font-weight: 400;
|
|
@@ -1119,11 +1182,19 @@
|
|
|
1119
1182
|
}
|
|
1120
1183
|
|
|
1121
1184
|
.flowsItemLink {
|
|
1122
|
-
display:
|
|
1185
|
+
display: flex;
|
|
1186
|
+
align-items: center;
|
|
1187
|
+
gap: 6px;
|
|
1123
1188
|
color: inherit;
|
|
1124
1189
|
text-decoration: none;
|
|
1125
1190
|
}
|
|
1126
1191
|
|
|
1192
|
+
.flowsItemPrivateIcon {
|
|
1193
|
+
color: var(--fgColor-muted, #656d76);
|
|
1194
|
+
flex-shrink: 0;
|
|
1195
|
+
margin-left: auto;
|
|
1196
|
+
}
|
|
1197
|
+
|
|
1127
1198
|
/* Avatar stack */
|
|
1128
1199
|
|
|
1129
1200
|
.avatarStack {
|