@dfosco/storyboard-react 4.2.0-beta.17 → 4.2.0-beta.19
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/package.json +7 -3
- package/src/BranchBar/BranchBar.jsx +3 -1
- package/src/BranchBar/BranchBar.module.css +2 -2
- package/src/BranchBar/useBranches.js +20 -6
- package/src/BranchBar/useBranches.test.js +68 -0
- package/src/CommandPalette/CommandPalette.jsx +250 -61
- package/src/CommandPalette/command-palette.css +12 -0
- package/src/Icon.jsx +46 -11
- package/src/Viewfinder.jsx +53 -133
- package/src/Viewfinder.module.css +20 -91
- package/src/Workspace.jsx +7 -0
- package/src/canvas/CanvasPage.jsx +601 -62
- package/src/canvas/CanvasPage.module.css +15 -2
- package/src/canvas/CanvasPage.multiselect.test.jsx +7 -0
- package/src/canvas/ConnectorLayer.jsx +120 -152
- package/src/canvas/ConnectorLayer.module.css +69 -0
- package/src/canvas/canvasApi.js +68 -2
- package/src/canvas/connectorGeometry.js +132 -0
- package/src/canvas/hotPoolDevLogs.js +25 -0
- package/src/canvas/useMarqueeSelect.js +30 -4
- package/src/canvas/widgets/CodePenEmbed.jsx +1 -0
- package/src/canvas/widgets/ComponentSetWidget.jsx +199 -0
- package/src/canvas/widgets/ComponentSetWidget.module.css +89 -0
- package/src/canvas/widgets/ComponentWidget.jsx +1 -0
- package/src/canvas/widgets/CropOverlay.jsx +219 -0
- package/src/canvas/widgets/CropOverlay.module.css +118 -0
- package/src/canvas/widgets/ExpandedPane.jsx +472 -0
- package/src/canvas/widgets/ExpandedPane.module.css +179 -0
- package/src/canvas/widgets/ExpandedPane.test.jsx +240 -0
- package/src/canvas/widgets/ExpandedPaneTopBar.jsx +111 -0
- package/src/canvas/widgets/ExpandedPaneTopBar.module.css +59 -0
- package/src/canvas/widgets/ExpandedPaneTopBar.test.jsx +45 -0
- package/src/canvas/widgets/FigmaEmbed.jsx +49 -102
- package/src/canvas/widgets/ImageWidget.jsx +129 -8
- package/src/canvas/widgets/ImageWidget.module.css +30 -0
- package/src/canvas/widgets/LinkPreview.jsx +93 -44
- package/src/canvas/widgets/MarkdownBlock.jsx +141 -16
- package/src/canvas/widgets/MarkdownBlock.module.css +25 -0
- package/src/canvas/widgets/PromptWidget.jsx +414 -0
- package/src/canvas/widgets/PromptWidget.module.css +273 -0
- package/src/canvas/widgets/PrototypeEmbed.jsx +46 -170
- package/src/canvas/widgets/ResizeHandle.jsx +17 -6
- package/src/canvas/widgets/StoryWidget.jsx +65 -11
- package/src/canvas/widgets/TerminalReadWidget.jsx +11 -5
- package/src/canvas/widgets/TerminalReadWidget.module.css +3 -1
- package/src/canvas/widgets/TerminalWidget.jsx +301 -124
- package/src/canvas/widgets/TerminalWidget.module.css +121 -12
- package/src/canvas/widgets/TilesWidget.jsx +302 -0
- package/src/canvas/widgets/TilesWidget.module.css +133 -0
- package/src/canvas/widgets/WidgetChrome.jsx +67 -152
- package/src/canvas/widgets/WidgetChrome.module.css +20 -1
- package/src/canvas/widgets/expandUtils.js +385 -16
- package/src/canvas/widgets/expandUtils.test.js +155 -0
- package/src/canvas/widgets/index.js +6 -2
- package/src/canvas/widgets/tilePool.js +23 -0
- package/src/canvas/widgets/tiles/diagonal-bl.png +0 -0
- package/src/canvas/widgets/tiles/diagonal-br.png +0 -0
- package/src/canvas/widgets/tiles/diagonal-tl.png +0 -0
- package/src/canvas/widgets/tiles/leaf.png +0 -0
- package/src/canvas/widgets/tiles/quarter-tl.png +0 -0
- package/src/canvas/widgets/tiles/quarter-tr.png +0 -0
- package/src/canvas/widgets/tiles/solid-a.png +0 -0
- package/src/canvas/widgets/tiles/solid-b.png +0 -0
- package/src/canvas/widgets/widgetConfig.js +37 -4
- package/src/canvas/widgets/widgetIcons.jsx +190 -0
- package/src/canvas/widgets/widgetProps.js +1 -0
- package/src/context.jsx +47 -19
- package/src/hooks/usePrototypeReloadGuard.js +64 -0
- package/src/index.js +4 -2
- package/src/story/ComponentSetPage.jsx +186 -0
- package/src/story/ComponentSetPage.module.css +121 -0
- package/src/story/StoryPage.jsx +32 -2
- package/src/vite/data-plugin.js +79 -35
- package/src/canvas/widgets/ActionWidget.jsx +0 -200
- package/src/canvas/widgets/ActionWidget.module.css +0 -122
- package/src/canvas/widgets/SplitExpandModal.jsx +0 -234
- package/src/canvas/widgets/SplitExpandModal.module.css +0 -335
- package/src/canvas/widgets/SplitScreenTopBar.jsx +0 -30
- package/src/canvas/widgets/SplitScreenTopBar.module.css +0 -58
package/src/Icon.jsx
CHANGED
|
@@ -40,16 +40,6 @@ const customIcons = {
|
|
|
40
40
|
'M4 12H20',
|
|
41
41
|
],
|
|
42
42
|
},
|
|
43
|
-
// Diamond grid icon (from StoryWidget/ComponentWidget title bar)
|
|
44
|
-
'component': {
|
|
45
|
-
viewBox: '0 0 24 24',
|
|
46
|
-
strokePaths: [
|
|
47
|
-
'M5.21173 15.1113L2.52473 12.4243C2.29041 12.1899 2.29041 11.8101 2.52473 11.5757L5.21173 8.88873C5.44605 8.65442 5.82595 8.65442 6.06026 8.88873L8.74727 11.5757C8.98158 11.8101 8.98158 12.1899 8.74727 12.4243L6.06026 15.1113C5.82595 15.3456 5.44605 15.3456 5.21173 15.1113Z',
|
|
48
|
-
'M11.5757 21.475L8.88874 18.788C8.65443 18.5537 8.65443 18.1738 8.88874 17.9395L11.5757 15.2525C11.8101 15.0182 12.19 15.0182 12.4243 15.2525L15.1113 17.9395C15.3456 18.1738 15.3456 18.5537 15.1113 18.788L12.4243 21.475C12.19 21.7094 11.8101 21.7094 11.5757 21.475Z',
|
|
49
|
-
'M17.9395 15.1113L15.2525 12.4243C15.0182 12.1899 15.0182 11.8101 15.2525 11.5757L17.9395 8.88873C18.1738 8.65442 18.5537 8.65442 18.788 8.88873L21.475 11.5757C21.7094 11.8101 21.7094 12.1899 21.475 12.4243L18.788 15.1113C18.5537 15.3456 18.1738 15.3456 17.9395 15.1113Z',
|
|
50
|
-
'M11.5757 8.74727L8.88874 6.06026C8.65443 5.82595 8.65443 5.44605 8.88874 5.21173L11.5757 2.52473C11.8101 2.29041 12.19 2.29041 12.4243 2.52473L15.1113 5.21173C15.3456 5.44605 15.3456 5.82595 15.1113 6.06026L12.4243 8.74727C12.19 8.98158 11.8101 8.98158 11.5757 8.74727Z',
|
|
51
|
-
],
|
|
52
|
-
},
|
|
53
43
|
// Smiley face icon (from assets/icons/canvas.svg)
|
|
54
44
|
'canvas': {
|
|
55
45
|
viewBox: '0 0 28 23',
|
|
@@ -60,10 +50,20 @@ const customIcons = {
|
|
|
60
50
|
'M17.6103 6.5C18.2731 6.5 18.8104 7.03731 18.8104 7.70012C18.8104 8.36293 18.2731 8.90025 17.6103 8.90025H17.5986C16.9358 8.90025 16.3984 8.36293 16.3984 7.70012C16.3984 7.03731 16.9358 6.5 17.5986 6.5H17.6103Z',
|
|
61
51
|
],
|
|
62
52
|
},
|
|
53
|
+
'sticky-note': {
|
|
54
|
+
viewBox: '0 0 14 14',
|
|
55
|
+
fillRule: 'evenodd',
|
|
56
|
+
path: 'M3.709.471C4.763.353 5.867.25 7 .25s2.237.104 3.29.22h.003a3.694 3.694 0 0 1 3.247 3.256v.004c.113 1.049.21 2.145.21 3.27q-.001.595-.032 1.176l-.008.067c-.556 3.437-3.804 5.226-6.192 5.498h-.006l-.048.006a.6.6 0 0 1-.126 0q-.168.003-.338.003c-1.133 0-2.236-.103-3.29-.221h-.003A3.695 3.695 0 0 1 .46 10.272v-.004C.346 9.221.25 8.126.25 7s.097-2.222.21-3.27v-.003A3.694 3.694 0 0 1 3.707.472zm8.784 7.047h-2.37c-.854 0-1.514.656-1.628 1.442c-.22 1.52-.706 2.546-1.413 3.54H7c-1.061 0-2.108-.097-3.15-.213a2.445 2.445 0 0 1-2.148-2.153C1.592 9.1 1.5 8.057 1.5 7s.091-2.1.202-3.134A2.444 2.444 0 0 1 3.85 1.714C4.89 1.597 5.938 1.5 7 1.5s2.107.098 3.151.213a2.444 2.444 0 0 1 2.147 2.152C12.408 4.9 12.5 5.944 12.5 7q0 .259-.007.518',
|
|
57
|
+
},
|
|
63
58
|
'agents': {
|
|
64
59
|
viewBox: '0 0 32 32',
|
|
65
60
|
path: 'M27.2 16c0-6.19-5.01-11.2-11.2-11.2S4.8 9.81 4.8 16S9.81 27.2 16 27.2S27.2 22.19 27.2 16m-5.6 2.1a1.4 1.4 0 0 1 0 2.8h-4.2a1.4 1.4 0 0 1 0-2.8zm-11.2-6.8a1.397 1.397 0 0 1 1.84.361l.08.119l2.1 3.5l.087.171a1.4 1.4 0 0 1 0 1.1l-.088.171l-2.1 3.5a1.4 1.4 0 0 1-2.4-1.44l1.67-2.78l-1.67-2.78l-.067-.127a1.394 1.394 0 0 1 .547-1.79zM30 16c0 7.73-6.27 14-14 14S2 23.73 2 16S8.27 2 16 2s14 6.27 14 14',
|
|
66
61
|
},
|
|
62
|
+
'codex': {
|
|
63
|
+
viewBox: '0 0 24 24',
|
|
64
|
+
fillRule: 'evenodd',
|
|
65
|
+
path: 'M8.086.457a6.105 6.105 0 013.046-.415c1.333.153 2.521.72 3.564 1.7a.117.117 0 00.107.029c1.408-.346 2.762-.224 4.061.366l.063.03.154.076c1.357.703 2.33 1.77 2.918 3.198.278.679.418 1.388.421 2.126a5.655 5.655 0 01-.18 1.631.167.167 0 00.04.155 5.982 5.982 0 011.578 2.891c.385 1.901-.01 3.615-1.183 5.14l-.182.22a6.063 6.063 0 01-2.934 1.851.162.162 0 00-.108.102c-.255.736-.511 1.364-.987 1.992-1.199 1.582-2.962 2.462-4.948 2.451-1.583-.008-2.986-.587-4.21-1.736a.145.145 0 00-.14-.032c-.518.167-1.04.191-1.604.185a5.924 5.924 0 01-2.595-.622 6.058 6.058 0 01-2.146-1.781c-.203-.269-.404-.522-.551-.821a7.74 7.74 0 01-.495-1.283 6.11 6.11 0 01-.017-3.064.166.166 0 00.008-.074.115.115 0 00-.037-.064 5.958 5.958 0 01-1.38-2.202 5.196 5.196 0 01-.333-1.589 6.915 6.915 0 01.188-2.132c.45-1.484 1.309-2.648 2.577-3.493.282-.188.55-.334.802-.438.286-.12.573-.22.861-.304a.129.129 0 00.087-.087A6.016 6.016 0 015.635 2.31C6.315 1.464 7.132.846 8.086.457zm-.804 7.85a.848.848 0 00-1.473.842l1.694 2.965-1.688 2.848a.849.849 0 001.46.864l1.94-3.272a.849.849 0 00.007-.854l-1.94-3.393zm5.446 6.24a.849.849 0 000 1.695h4.848a.849.849 0 000-1.696h-4.848z',
|
|
66
|
+
},
|
|
67
67
|
'claude': {
|
|
68
68
|
viewBox: '0 0 24 24',
|
|
69
69
|
path: 'm4.7144 15.9555 4.7174-2.6471.079-.2307-.079-.1275h-.2307l-.7893-.0486-2.6956-.0729-2.3375-.0971-2.2646-.1214-.5707-.1215-.5343-.7042.0546-.3522.4797-.3218.686.0608 1.5179.1032 2.2767.1578 1.6514.0972 2.4468.255h.3886l.0546-.1579-.1336-.0971-.1032-.0972L6.973 9.8356l-2.55-1.6879-1.3356-.9714-.7225-.4918-.3643-.4614-.1578-1.0078.6557-.7225.8803.0607.2246.0607.8925.686 1.9064 1.4754 2.4893 1.8336.3643.3035.1457-.1032.0182-.0728-.164-.2733-1.3539-2.4467-1.445-2.4893-.6435-1.032-.17-.6194c-.0607-.255-.1032-.4674-.1032-.7285L6.287.1335 6.6997 0l.9957.1336.419.3642.6192 1.4147 1.0018 2.2282 1.5543 3.0296.4553.8985.2429.8318.091.255h.1579v-.1457l.1275-1.706.2368-2.0947.2307-2.6957.0789-.7589.3764-.9107.7468-.4918.5828.2793.4797.686-.0668.4433-.2853 1.8517-.5586 2.9021-.3643 1.9429h.2125l.2429-.2429.9835-1.3053 1.6514-2.0643.7286-.8196.85-.9046.5464-.4311h1.0321l.759 1.1293-.34 1.1657-1.0625 1.3478-.8804 1.1414-1.2628 1.7-.7893 1.36.0729.1093.1882-.0183 2.8535-.607 1.5421-.2794 1.8396-.3157.8318.3886.091.3946-.3278.8075-1.967.4857-2.3072.4614-3.4364.8136-.0425.0304.0486.0607 1.5482.1457.6618.0364h1.621l3.0175.2247.7892.522.4736.6376-.079.4857-1.2142.6193-1.6393-.3886-3.825-.9107-1.3113-.3279h-.1822v.1093l1.0929 1.0686 2.0035 1.8092 2.5075 2.3314.1275.5768-.3218.4554-.34-.0486-2.2039-1.6575-.85-.7468-1.9246-1.621h-.1275v.17l.4432.6496 2.3436 3.5214.1214 1.0807-.17.3521-.6071.2125-.6679-.1214-1.3721-1.9246L14.38 17.959l-1.1414-1.9428-.1397.079-.674 7.2552-.3156.3703-.7286.2793-.6071-.4614-.3218-.7468.3218-1.4753.3886-1.9246.3157-1.53.2853-1.9004.17-.6314-.0121-.0425-.1397.0182-1.4328 1.9672-2.1796 2.9446-1.7243 1.8456-.4128.164-.7164-.3704.0667-.6618.4008-.5889 2.386-3.0357 1.4389-1.882.929-1.0868-.0062-.1579h-.0546l-6.3385 4.1164-1.1293.1457-.4857-.4554.0608-.7467.2307-.2429 1.9064-1.3114Z',
|
|
@@ -121,6 +121,41 @@ const iconoirIcons = {
|
|
|
121
121
|
strokeWidth: '1.5',
|
|
122
122
|
content: '<path d="M3 21V3.6C3 3.26863 3.26863 3 3.6 3H21" stroke="currentColor"/><path d="M17 21H20.4C20.7314 21 21 20.7314 21 20.4V17" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"/><path d="M21 7V9" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"/><path d="M21 12V14" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"/><path d="M7 21H9" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"/><path d="M12 21H14" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"/><path d="M3 4C3.55228 4 4 3.55228 4 3C4 2.44772 3.55228 2 3 2C2.44772 2 2 2.44772 2 3C2 3.55228 2.44772 4 3 4Z" fill="currentColor" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"/><path d="M3 22C3.55228 22 4 21.5523 4 21C4 20.4477 3.55228 20 3 20C2.44772 20 2 20.4477 2 21C2 21.5523 2.44772 22 3 22Z" fill="currentColor" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"/><path d="M21 4C21.5523 4 22 3.55228 22 3C22 2.44772 21.5523 2 21 2C20.4477 2 20 2.44772 20 3C20 3.55228 20.4477 4 21 4Z" fill="currentColor" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"/>',
|
|
123
123
|
},
|
|
124
|
+
'white-flag': {
|
|
125
|
+
viewBox: '0 0 24 24',
|
|
126
|
+
strokeWidth: '1.5',
|
|
127
|
+
content: '<path d="M5 15L5.95039 4.54568C5.97849 4.23663 6.23761 4 6.54793 4H20.343C20.6958 4 20.9725 4.30295 20.9405 4.65432L20.0496 14.4543C20.0215 14.7634 19.7624 15 19.4521 15H5ZM5 15L4.4 21" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"/>',
|
|
128
|
+
},
|
|
129
|
+
'light-bulb': {
|
|
130
|
+
viewBox: '0 0 24 24',
|
|
131
|
+
strokeWidth: '1.5',
|
|
132
|
+
content: '<path d="M9 18H15" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"/><path d="M10 21H14" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"/><path d="M9.00082 15C9.00098 13 8.50098 12.5 7.50082 11.5C6.50067 10.5 6.02422 9.48689 6.00082 8C5.95284 4.95029 8.00067 3 12.0008 3C16.001 3 18.0488 4.95029 18.0008 8C17.9774 9.48689 17.5007 10.5 16.5008 11.5C15.501 12.5 15.001 13 15.0008 15" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"/>',
|
|
133
|
+
},
|
|
134
|
+
'light-bulb-off': {
|
|
135
|
+
viewBox: '0 0 24 24',
|
|
136
|
+
strokeWidth: '1.5',
|
|
137
|
+
content: '<path d="M9 18H15" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"/><path d="M10 21H14" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"/><path d="M16.4999 11.5C17.4997 10.5 17.9765 9.48689 17.9999 8C18.0479 4.95029 16 3 11.9999 3C10.8324 3 9.83119 3.16613 8.99988 3.47724" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"/><path d="M8.99985 15C9 13 8.5 12.5 7.49985 11.5C6.4997 10.5 6.02324 9.48689 5.99985 8C5.99142 7.46458 6.0476 6.96304 6.1676 6.5" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"/><path d="M3 3L21 21" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"/>',
|
|
138
|
+
},
|
|
139
|
+
'keyframes': {
|
|
140
|
+
viewBox: '0 0 24 24',
|
|
141
|
+
strokeWidth: '1.5',
|
|
142
|
+
content: '<path d="M13.8476 13.317L9.50515 18.2798C8.70833 19.1905 7.29167 19.1905 6.49485 18.2798L2.15238 13.317C1.49259 12.563 1.49259 11.437 2.15238 10.683L6.49485 5.72018C7.29167 4.80952 8.70833 4.80952 9.50515 5.72017L13.8476 10.683C14.5074 11.437 14.5074 12.563 13.8476 13.317Z" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"/><path d="M13 19L17.8844 13.3016C18.5263 12.5526 18.5263 11.4474 17.8844 10.6984L13 5" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"/><path d="M17 19L21.8844 13.3016C22.5263 12.5526 22.5263 11.4474 21.8844 10.6984L17 5" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"/>',
|
|
143
|
+
},
|
|
144
|
+
'keyframes-couple-solid': {
|
|
145
|
+
viewBox: '0 0 24 24',
|
|
146
|
+
fill: true,
|
|
147
|
+
content: '<path fill-rule="evenodd" clip-rule="evenodd" d="M14.0658 5.18029L12.5606 6.87362L11.4395 5.87707L12.9447 4.18374C14.0386 2.95308 15.9614 2.95308 17.0554 4.18373L22.3794 10.1733C23.3056 11.2152 23.3057 12.7855 22.3795 13.8273L17.0554 19.8169C15.9614 21.0476 14.0386 21.0477 12.9447 19.8169L11.4395 18.1236L12.5606 17.1271L14.0658 18.8204C14.563 19.3798 15.437 19.3798 15.9342 18.8204L21.2583 12.8308C21.6793 12.3572 21.6793 11.6435 21.2584 11.17L15.9343 5.18029C15.437 4.6209 14.563 4.6209 14.0658 5.18029" fill="currentColor"/><path d="M6.94474 4.18374C8.03866 2.95307 9.96152 2.95308 11.0555 4.18374L16.3795 10.1733C17.3057 11.2152 17.3058 12.7855 16.3796 13.8273L11.0555 19.8169C9.96155 21.0476 8.03866 21.0477 6.94474 19.8169L1.62067 13.8273C0.694507 12.7855 0.694485 11.2152 1.62064 10.1734L6.94474 4.18374Z" fill="currentColor"/>',
|
|
148
|
+
},
|
|
149
|
+
'keyframe': {
|
|
150
|
+
viewBox: '0 0 24 24',
|
|
151
|
+
strokeWidth: '1.5',
|
|
152
|
+
content: '<path d="M20.777 13.3453L13.4799 21.3721C12.6864 22.245 11.3136 22.245 10.5201 21.3721L3.22304 13.3453C2.52955 12.5825 2.52955 11.4175 3.22304 10.6547L10.5201 2.62787C11.3136 1.755 12.6864 1.755 13.4799 2.62787L20.777 10.6547C21.4705 11.4175 21.4705 12.5825 20.777 13.3453Z" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"/>',
|
|
153
|
+
},
|
|
154
|
+
'wrench': {
|
|
155
|
+
viewBox: '0 0 24 24',
|
|
156
|
+
strokeWidth: '1.5',
|
|
157
|
+
content: '<path d="M10.0503 10.6066L2.97923 17.6777C2.19818 18.4587 2.19818 19.725 2.97923 20.5061V20.5061C3.76027 21.2871 5.0266 21.2871 5.80765 20.5061L12.8787 13.435" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"/><path d="M10.0502 10.6066C9.20638 8.45358 9.37134 5.6286 11.1109 3.88909C12.8504 2.14957 16.0606 1.76777 17.8284 2.82843L14.7877 5.8691L14.5051 8.98014L17.6161 8.69753L20.6568 5.65685C21.7175 7.42462 21.3357 10.6349 19.5961 12.3744C17.8566 14.1139 15.0316 14.2789 12.8786 13.435" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"/>',
|
|
158
|
+
},
|
|
124
159
|
}
|
|
125
160
|
|
|
126
161
|
/* ─── React Component ─── */
|
|
@@ -176,7 +211,7 @@ export default function Icon({
|
|
|
176
211
|
if (custom.path) {
|
|
177
212
|
svgContent = (
|
|
178
213
|
<svg width={size} height={size} viewBox={custom.viewBox} fill="currentColor" {...ariaProps}>
|
|
179
|
-
<path d={custom.path} />
|
|
214
|
+
<path d={custom.path} fillRule={custom.fillRule} clipRule={custom.fillRule} />
|
|
180
215
|
</svg>
|
|
181
216
|
)
|
|
182
217
|
} else if (custom.strokePaths) {
|
package/src/Viewfinder.jsx
CHANGED
|
@@ -1,15 +1,16 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
2
|
+
* Workspace — SaaS-style homescreen for Storyboard.
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
4
|
+
* Sidebar + grid layout wired to real data from buildPrototypeIndex and listStories.
|
|
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 { buildPrototypeIndex, listStories, getStoryData, getLocal, setLocal } from '@dfosco/storyboard-core'
|
|
8
|
+
import { buildPrototypeIndex, listStories, getStoryData, getLocal, setLocal, BranchSelect } from '@dfosco/storyboard-core'
|
|
9
9
|
import { MarkGithubIcon, GitBranchIcon, ChevronDownIcon, ChevronRightIcon, FileDirectoryFillIcon, PlusIcon, StarIcon, StarFillIcon, ThreeBarsIcon, XIcon, StackIcon, TrashIcon, ShieldLockIcon, KebabHorizontalIcon, PencilIcon } from '@primer/octicons-react'
|
|
10
10
|
import { Menu } from '@base-ui/react/menu'
|
|
11
11
|
import { Dialog } from '@base-ui/react/dialog'
|
|
12
12
|
import Icon from './Icon.jsx'
|
|
13
|
+
import { useBranches } from './BranchBar/useBranches.js'
|
|
13
14
|
import css from './Viewfinder.module.css'
|
|
14
15
|
|
|
15
16
|
/* ─── Theme sync: read toolbar theme from DOM and apply to Primer/BaseUI ─── */
|
|
@@ -94,10 +95,10 @@ function useGitHubUser(basePath) {
|
|
|
94
95
|
|
|
95
96
|
/* ─── localStorage helpers ─── */
|
|
96
97
|
|
|
97
|
-
const STARRED_KEY = 'sb-
|
|
98
|
-
const RECENT_KEY = 'sb-
|
|
98
|
+
const STARRED_KEY = 'sb-workspace-starred'
|
|
99
|
+
const RECENT_KEY = 'sb-workspace-recent'
|
|
99
100
|
const MAX_RECENT = 30
|
|
100
|
-
const GROUP_BY_FOLDERS_KEY = 'sb-
|
|
101
|
+
const GROUP_BY_FOLDERS_KEY = 'sb-workspace-group-folders'
|
|
101
102
|
|
|
102
103
|
function readJSON(key, fallback) {
|
|
103
104
|
try { return JSON.parse(localStorage.getItem(key)) || fallback }
|
|
@@ -175,7 +176,7 @@ function getTypeLabel(type) {
|
|
|
175
176
|
function getTypeIcon(type, size = 14) {
|
|
176
177
|
if (type === 'prototype') return <Icon name="prototype" size={size} />
|
|
177
178
|
if (type === 'canvas') return <Icon name="canvas" size={size} />
|
|
178
|
-
if (type === 'component') return <Icon name="
|
|
179
|
+
if (type === 'component') return <Icon name="iconoir/keyframe" size={size} />
|
|
179
180
|
return null
|
|
180
181
|
}
|
|
181
182
|
|
|
@@ -875,7 +876,7 @@ function CreateMenu({ onClose, basePath }) {
|
|
|
875
876
|
const items = [
|
|
876
877
|
{ icon: <Icon name="canvas" size={18} />, title: 'Canvas', desc: 'Interactive board for prototypes, components, and documents' },
|
|
877
878
|
{ icon: <Icon name="prototype" size={18} />, title: 'Prototype', desc: 'Interactive page flow' },
|
|
878
|
-
{ icon: <Icon name="
|
|
879
|
+
{ icon: <Icon name="iconoir/-couple-solid" size={18} />, title: 'Component', desc: 'Reusable component' },
|
|
879
880
|
]
|
|
880
881
|
|
|
881
882
|
const moreItems = [
|
|
@@ -945,141 +946,60 @@ const NAV_ITEMS = [
|
|
|
945
946
|
|
|
946
947
|
const TAB_FILTERS = ['All', 'Recent', 'Starred']
|
|
947
948
|
|
|
948
|
-
/* ─── Branch
|
|
949
|
+
/* ─── Branch Navigation ─── */
|
|
949
950
|
|
|
950
|
-
function
|
|
951
|
-
const [branches, setBranches] = useState(() => {
|
|
952
|
-
if (typeof window !== 'undefined' && Array.isArray(window.__SB_BRANCHES__)) {
|
|
953
|
-
return window.__SB_BRANCHES__
|
|
954
|
-
}
|
|
955
|
-
return null
|
|
956
|
-
})
|
|
957
|
-
|
|
958
|
-
const [gitUser, setGitUser] = useState(null)
|
|
959
|
-
|
|
960
|
-
useEffect(() => {
|
|
961
|
-
const apiBase = (basePath || '/').replace(/\/$/, '')
|
|
962
|
-
|
|
963
|
-
// Fetch git user info for "my branches" filtering
|
|
964
|
-
fetch(`${apiBase}/_storyboard/git-user`).then(r => r.ok ? r.json() : null)
|
|
965
|
-
.then(data => { if (data?.name) setGitUser(data.name) })
|
|
966
|
-
.catch(() => {})
|
|
967
|
-
|
|
968
|
-
// Always fetch live branch list from server API
|
|
969
|
-
fetch(`${apiBase}/_storyboard/worktrees`).then(r => r.ok ? r.json() : null)
|
|
970
|
-
.then(data => { if (Array.isArray(data) && data.length > 0) setBranches(data) })
|
|
971
|
-
.catch(() => {})
|
|
972
|
-
}, [])
|
|
973
|
-
|
|
974
|
-
const currentBranch = useMemo(() => {
|
|
975
|
-
const m = (basePath || '').match(/\/branch--([^/]+)\/?$/)
|
|
976
|
-
return m ? m[1] : 'main'
|
|
977
|
-
}, [basePath])
|
|
978
|
-
|
|
979
|
-
const branchBasePath = (basePath || '/').replace(/\/branch--[^/]*\/$/, '/')
|
|
980
|
-
|
|
981
|
-
return { branches, currentBranch, branchBasePath, gitUser }
|
|
982
|
-
}
|
|
983
|
-
|
|
984
|
-
function BranchDropdown({ basePath }) {
|
|
985
|
-
// Dev: hide dropdown — use CLI to switch branches
|
|
951
|
+
function BranchNav({ basePath }) {
|
|
986
952
|
const isLocalDev = typeof window !== 'undefined' && window.__SB_LOCAL_DEV__ === true
|
|
987
|
-
|
|
988
|
-
|
|
989
|
-
const { branches, currentBranch, branchBasePath, gitUser } = useBranches(basePath)
|
|
990
|
-
const [showAll, setShowAll] = useState(false)
|
|
953
|
+
const { branches, currentBranch, branchBasePath } = useBranches(basePath)
|
|
991
954
|
const [switching, setSwitching] = useState(null)
|
|
992
|
-
const [switchError, setSwitchError] = useState(null)
|
|
993
955
|
|
|
994
956
|
if (!branches || branches.length === 0) return null
|
|
995
957
|
|
|
996
|
-
const
|
|
958
|
+
const branchNames = branches.map(b => b.branch)
|
|
997
959
|
|
|
998
|
-
|
|
999
|
-
|
|
1000
|
-
|
|
1001
|
-
|
|
960
|
+
const navigate = async (branch) => {
|
|
961
|
+
if (switching) return
|
|
962
|
+
const target = branches.find(b => b.branch === branch)
|
|
963
|
+
const folder = target?.folder || (branch === 'main' ? '' : `branch--${branch}/`)
|
|
964
|
+
const directUrl = `${branchBasePath}${folder}`
|
|
1002
965
|
|
|
1003
|
-
|
|
1004
|
-
|
|
1005
|
-
|
|
1006
|
-
|
|
1007
|
-
? [...otherBranches].sort((a, b) => (a.branch || '').localeCompare(b.branch || ''))
|
|
1008
|
-
: otherBranches
|
|
1009
|
-
.filter(b => !b.lastModified || new Date(b.lastModified).getTime() > twoWeeksAgo)
|
|
1010
|
-
.sort((a, b) => (a.branch || '').localeCompare(b.branch || ''))
|
|
966
|
+
if (!isLocalDev) {
|
|
967
|
+
window.location.href = directUrl
|
|
968
|
+
return
|
|
969
|
+
}
|
|
1011
970
|
|
|
1012
|
-
|
|
971
|
+
// Local dev: ask server to spin up the branch, then navigate
|
|
1013
972
|
setSwitching(branch)
|
|
1014
|
-
const
|
|
1015
|
-
|
|
973
|
+
const apiBase = (basePath || '/').replace(/\/$/, '')
|
|
974
|
+
try {
|
|
975
|
+
const res = await fetch(`${apiBase}/_storyboard/switch-branch`, {
|
|
976
|
+
method: 'POST',
|
|
977
|
+
headers: { 'Content-Type': 'application/json' },
|
|
978
|
+
body: JSON.stringify({ branch }),
|
|
979
|
+
})
|
|
980
|
+
const data = await res.json()
|
|
981
|
+
window.location.href = (res.ok && data.url) ? data.url : directUrl
|
|
982
|
+
} catch {
|
|
983
|
+
window.location.href = directUrl
|
|
984
|
+
}
|
|
1016
985
|
}
|
|
1017
986
|
|
|
1018
987
|
return (
|
|
1019
|
-
|
|
1020
|
-
<
|
|
988
|
+
<>
|
|
989
|
+
<div className={css.branchNav}>
|
|
1021
990
|
<GitBranchIcon size={14} />
|
|
1022
|
-
<
|
|
1023
|
-
|
|
1024
|
-
|
|
1025
|
-
|
|
1026
|
-
|
|
1027
|
-
|
|
1028
|
-
|
|
1029
|
-
|
|
1030
|
-
|
|
1031
|
-
|
|
1032
|
-
|
|
1033
|
-
|
|
1034
|
-
className={`${css.branchItem}${b.branch === currentBranch ? ` ${css.branchItemActive}` : ''}`}
|
|
1035
|
-
onClick={() => switchBranch(b.branch)}
|
|
1036
|
-
>
|
|
1037
|
-
<GitBranchIcon size={12} />
|
|
1038
|
-
{b.branch}
|
|
1039
|
-
</Menu.Item>
|
|
1040
|
-
))}
|
|
1041
|
-
</>
|
|
1042
|
-
)}
|
|
1043
|
-
|
|
1044
|
-
{myBranches.length > 0 && recentBranches.length > 0 && (
|
|
1045
|
-
<div className={css.branchSeparator} />
|
|
1046
|
-
)}
|
|
1047
|
-
|
|
1048
|
-
{recentBranches.length > 0 && (
|
|
1049
|
-
<>
|
|
1050
|
-
<div className={css.branchSectionLabel}>
|
|
1051
|
-
{showAll ? 'All branches' : 'Recent branches'}
|
|
1052
|
-
</div>
|
|
1053
|
-
<Menu.Viewport className={css.branchViewport}>
|
|
1054
|
-
{recentBranches.map(b => (
|
|
1055
|
-
<Menu.Item
|
|
1056
|
-
key={b.branch}
|
|
1057
|
-
className={`${css.branchItem}${b.branch === currentBranch ? ` ${css.branchItemActive}` : ''}`}
|
|
1058
|
-
onClick={() => switchBranch(b.branch)}
|
|
1059
|
-
>
|
|
1060
|
-
<GitBranchIcon size={12} />
|
|
1061
|
-
{b.branch}
|
|
1062
|
-
</Menu.Item>
|
|
1063
|
-
))}
|
|
1064
|
-
</Menu.Viewport>
|
|
1065
|
-
</>
|
|
1066
|
-
)}
|
|
1067
|
-
|
|
1068
|
-
{!showAll && otherBranches.length > recentBranches.length && (
|
|
1069
|
-
<>
|
|
1070
|
-
<div className={css.branchSeparator} />
|
|
1071
|
-
<button
|
|
1072
|
-
className={css.branchShowAll}
|
|
1073
|
-
onClick={(e) => { e.stopPropagation(); setShowAll(true) }}
|
|
1074
|
-
>
|
|
1075
|
-
See all branches ({otherBranches.length})
|
|
1076
|
-
</button>
|
|
1077
|
-
</>
|
|
1078
|
-
)}
|
|
1079
|
-
</Menu.Popup>
|
|
1080
|
-
</Menu.Positioner>
|
|
1081
|
-
</Menu.Portal>
|
|
1082
|
-
</Menu.Root>
|
|
991
|
+
<BranchSelect
|
|
992
|
+
branches={branchNames}
|
|
993
|
+
value={currentBranch}
|
|
994
|
+
onChange={(e) => navigate(e.target.value)}
|
|
995
|
+
disabled={!!switching}
|
|
996
|
+
/>
|
|
997
|
+
</div>
|
|
998
|
+
{switching && <div className={css.switchOverlay}>
|
|
999
|
+
<div className={css.switchSpinner} />
|
|
1000
|
+
<span>Starting {switching}…</span>
|
|
1001
|
+
</div>}
|
|
1002
|
+
</>
|
|
1083
1003
|
)
|
|
1084
1004
|
}
|
|
1085
1005
|
|
|
@@ -1153,7 +1073,7 @@ function UserSettingsDialog({ open, onOpenChange, user, onRemoveToken }) {
|
|
|
1153
1073
|
|
|
1154
1074
|
/* ─── Main Component ─── */
|
|
1155
1075
|
|
|
1156
|
-
export default function
|
|
1076
|
+
export default function Workspace({
|
|
1157
1077
|
pageModules = {},
|
|
1158
1078
|
basePath,
|
|
1159
1079
|
title = 'Storyboard',
|
|
@@ -1179,7 +1099,7 @@ export default function Viewfinder({
|
|
|
1179
1099
|
const knownRoutes = useMemo(() =>
|
|
1180
1100
|
Object.keys(pageModules)
|
|
1181
1101
|
.map(p => p.replace('/src/prototypes/', '').replace('.jsx', ''))
|
|
1182
|
-
.filter(n => !n.startsWith('_') && n !== 'index' && n !== 'viewfinder'),
|
|
1102
|
+
.filter(n => !n.startsWith('_') && n !== 'index' && n !== 'workspace' && n !== 'viewfinder'),
|
|
1183
1103
|
[pageModules],
|
|
1184
1104
|
)
|
|
1185
1105
|
|
|
@@ -1392,7 +1312,7 @@ export default function Viewfinder({
|
|
|
1392
1312
|
</div>
|
|
1393
1313
|
</div>
|
|
1394
1314
|
<div className={css.topActions}>
|
|
1395
|
-
<
|
|
1315
|
+
<BranchNav basePath={basePath} />
|
|
1396
1316
|
{isLocalDev && (
|
|
1397
1317
|
<Menu.Root open={showCreate} onOpenChange={setShowCreate}>
|
|
1398
1318
|
<Menu.Trigger className={css.createBtn}>
|
|
@@ -81,110 +81,39 @@
|
|
|
81
81
|
|
|
82
82
|
/* Branch dropdown */
|
|
83
83
|
|
|
84
|
-
.
|
|
84
|
+
.branchNav {
|
|
85
85
|
display: flex;
|
|
86
86
|
align-items: center;
|
|
87
87
|
gap: 6px;
|
|
88
|
-
padding: 7px 14px;
|
|
89
|
-
background: var(--bgColor-default, #fff);
|
|
90
88
|
color: var(--fgColor-muted, #555);
|
|
91
|
-
border: 1px solid var(--borderColor-default, #e5e5e5);
|
|
92
|
-
border-radius: 8px;
|
|
93
|
-
font-size: 16px;
|
|
94
|
-
font-weight: 500;
|
|
95
|
-
cursor: pointer;
|
|
96
|
-
transition: all 0.15s;
|
|
97
|
-
font-family: inherit;
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
.branchBtn:hover {
|
|
101
|
-
background: var(--bgColor-muted, #f5f5f5);
|
|
102
|
-
border-color: var(--borderColor-muted);
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
.branchBtnText {
|
|
106
|
-
max-width: 160px;
|
|
107
|
-
overflow: hidden;
|
|
108
|
-
text-overflow: ellipsis;
|
|
109
|
-
white-space: nowrap;
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
.branchPositioner {
|
|
113
|
-
z-index: 200;
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
.branchPopup {
|
|
117
|
-
background: var(--bgColor-default, #fff);
|
|
118
|
-
border: 1px solid var(--borderColor-default, #e5e5e5);
|
|
119
|
-
border-radius: 10px;
|
|
120
|
-
box-shadow: 0 8px 32px rgba(0, 0, 0, 0.1);
|
|
121
|
-
min-width: 240px;
|
|
122
|
-
max-width: 320px;
|
|
123
|
-
padding: 6px 0;
|
|
124
|
-
font-family: 'Mona Sans', -apple-system, BlinkMacSystemFont, sans-serif;
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
.branchSectionLabel {
|
|
128
|
-
padding: 8px 14px 4px;
|
|
129
|
-
font-size: 14px;
|
|
130
|
-
font-weight: 600;
|
|
131
|
-
color: var(--fgColor-muted, #999);
|
|
132
|
-
text-transform: uppercase;
|
|
133
|
-
letter-spacing: 0.4px;
|
|
134
89
|
}
|
|
135
90
|
|
|
136
|
-
.
|
|
91
|
+
.switchOverlay {
|
|
92
|
+
position: fixed;
|
|
93
|
+
inset: 0;
|
|
94
|
+
z-index: 9999;
|
|
137
95
|
display: flex;
|
|
96
|
+
flex-direction: column;
|
|
138
97
|
align-items: center;
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
98
|
+
justify-content: center;
|
|
99
|
+
gap: 12px;
|
|
100
|
+
background: var(--bgColor-default, #fff);
|
|
142
101
|
color: var(--fgColor-muted, #555);
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
border: none;
|
|
146
|
-
background: none;
|
|
147
|
-
width: 100%;
|
|
148
|
-
text-align: left;
|
|
149
|
-
}
|
|
150
|
-
|
|
151
|
-
.branchItem:hover,
|
|
152
|
-
.branchItem[data-highlighted] {
|
|
153
|
-
background: var(--bgColor-muted, #f5f5f5);
|
|
154
|
-
}
|
|
155
|
-
|
|
156
|
-
.branchItemActive {
|
|
157
|
-
composes: branchItem;
|
|
158
|
-
color: var(--fgColor-default, #1a1a1a);
|
|
159
|
-
font-weight: 600;
|
|
160
|
-
}
|
|
161
|
-
|
|
162
|
-
.branchSeparator {
|
|
163
|
-
height: 1px;
|
|
164
|
-
background: var(--borderColor-default, #e5e5e5);
|
|
165
|
-
margin: 4px 10px;
|
|
166
|
-
}
|
|
167
|
-
|
|
168
|
-
.branchViewport {
|
|
169
|
-
max-height: 280px;
|
|
170
|
-
overflow-y: auto;
|
|
102
|
+
font-size: 15px;
|
|
103
|
+
font-weight: 500;
|
|
171
104
|
}
|
|
172
105
|
|
|
173
|
-
.
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
border: none;
|
|
181
|
-
cursor: pointer;
|
|
182
|
-
text-align: left;
|
|
183
|
-
font-family: inherit;
|
|
106
|
+
.switchSpinner {
|
|
107
|
+
width: 24px;
|
|
108
|
+
height: 24px;
|
|
109
|
+
border: 3px solid var(--borderColor-default, #e5e5e5);
|
|
110
|
+
border-top-color: var(--fgColor-accent, #2563eb);
|
|
111
|
+
border-radius: 50%;
|
|
112
|
+
animation: branchSpin 0.6s linear infinite;
|
|
184
113
|
}
|
|
185
114
|
|
|
186
|
-
|
|
187
|
-
|
|
115
|
+
@keyframes branchSpin {
|
|
116
|
+
to { transform: rotate(360deg); }
|
|
188
117
|
}
|
|
189
118
|
|
|
190
119
|
/* ─── Body: sidebar + content ─── */
|