@r2digisolutions/components 0.1.7 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (350) hide show
  1. package/dist/components/atoms/IconButton/IconButton.svelte +1 -1
  2. package/dist/components/atoms/MediaKindIcon/MediaKindIcon.stories.js +8 -0
  3. package/dist/components/atoms/MediaKindIcon/MediaKindIcon.svelte +122 -0
  4. package/dist/components/atoms/MediaKindIcon/MediaKindIcon.svelte.d.ts +11 -0
  5. package/dist/components/atoms/MediaKindIcon/MediaKindIconStory.svelte +12 -0
  6. package/dist/components/atoms/MediaKindIcon/MediaKindIconStory.svelte.d.ts +18 -0
  7. package/dist/components/atoms/PanKnob/PanKnob.stories.d.ts +9 -0
  8. package/dist/components/atoms/PanKnob/PanKnob.stories.js +8 -0
  9. package/dist/components/atoms/PanKnob/PanKnob.svelte +218 -0
  10. package/dist/components/atoms/PanKnob/PanKnob.svelte.d.ts +19 -0
  11. package/dist/components/atoms/PanKnob/PanKnobStory.svelte +15 -0
  12. package/dist/components/atoms/PanKnob/PanKnobStory.svelte.d.ts +3 -0
  13. package/dist/components/atoms/Playhead/Playhead.stories.js +8 -0
  14. package/dist/components/atoms/Playhead/Playhead.svelte +98 -0
  15. package/dist/components/atoms/Playhead/Playhead.svelte.d.ts +21 -0
  16. package/dist/components/atoms/Playhead/PlayheadStory.svelte +9 -0
  17. package/dist/components/atoms/Playhead/PlayheadStory.svelte.d.ts +18 -0
  18. package/dist/components/atoms/TimeRuler/TimeRuler.stories.js +8 -0
  19. package/dist/components/atoms/TimeRuler/TimeRuler.svelte +117 -0
  20. package/dist/components/atoms/TimeRuler/TimeRuler.svelte.d.ts +17 -0
  21. package/dist/components/atoms/TimeRuler/TimeRulerStory.svelte +7 -0
  22. package/dist/components/atoms/TimeRuler/TimeRulerStory.svelte.d.ts +18 -0
  23. package/dist/components/atoms/TimelineGrid/TimelineGrid.stories.js +8 -0
  24. package/dist/components/atoms/TimelineGrid/TimelineGrid.svelte +39 -0
  25. package/dist/components/atoms/TimelineGrid/TimelineGrid.svelte.d.ts +11 -0
  26. package/dist/components/atoms/TimelineGrid/TimelineGridStory.svelte +7 -0
  27. package/dist/components/atoms/TimelineGrid/TimelineGridStory.svelte.d.ts +18 -0
  28. package/dist/components/atoms/Tooltip/Tooltip.svelte +1 -1
  29. package/dist/components/atoms/TrimHandle/TrimHandle.stories.js +8 -0
  30. package/dist/components/atoms/TrimHandle/TrimHandle.svelte +63 -0
  31. package/dist/components/atoms/TrimHandle/TrimHandle.svelte.d.ts +12 -0
  32. package/dist/components/atoms/TrimHandle/TrimHandleStory.svelte +11 -0
  33. package/dist/components/atoms/TrimHandle/TrimHandleStory.svelte.d.ts +18 -0
  34. package/dist/components/molecules/AiAssistPanel/AiAssistPanel.stories.d.ts +9 -0
  35. package/dist/components/molecules/AiAssistPanel/AiAssistPanel.stories.js +8 -0
  36. package/dist/components/molecules/AiAssistPanel/AiAssistPanel.svelte +102 -0
  37. package/dist/components/molecules/AiAssistPanel/AiAssistPanel.svelte.d.ts +20 -0
  38. package/dist/components/molecules/AiAssistPanel/AiAssistPanelStory.svelte +34 -0
  39. package/dist/components/molecules/AiAssistPanel/AiAssistPanelStory.svelte.d.ts +3 -0
  40. package/dist/components/molecules/BulkActionBar/BulkActionBar.svelte +97 -61
  41. package/dist/components/molecules/BulkActionBar/BulkActionBar.svelte.d.ts +2 -0
  42. package/dist/components/molecules/BulkEditPanel/BulkEditPanel.stories.js +8 -0
  43. package/dist/components/molecules/BulkEditPanel/BulkEditPanel.svelte +117 -0
  44. package/dist/components/molecules/BulkEditPanel/BulkEditPanel.svelte.d.ts +23 -0
  45. package/dist/components/molecules/BulkEditPanel/BulkEditPanelStory.svelte +18 -0
  46. package/dist/components/molecules/BulkEditPanel/BulkEditPanelStory.svelte.d.ts +18 -0
  47. package/dist/components/molecules/CanvasElementsPanel/CanvasElementsPanel.stories.js +8 -0
  48. package/dist/components/molecules/CanvasElementsPanel/CanvasElementsPanel.svelte +858 -0
  49. package/dist/components/molecules/CanvasElementsPanel/CanvasElementsPanel.svelte.d.ts +43 -0
  50. package/dist/components/molecules/CanvasElementsPanel/CanvasElementsPanelStory.svelte +7 -0
  51. package/dist/components/molecules/CanvasElementsPanel/CanvasElementsPanelStory.svelte.d.ts +18 -0
  52. package/dist/components/molecules/CanvasInspector/CanvasInspector.stories.d.ts +9 -0
  53. package/dist/components/molecules/CanvasInspector/CanvasInspector.stories.js +8 -0
  54. package/dist/components/molecules/CanvasInspector/CanvasInspector.svelte +1140 -0
  55. package/dist/components/molecules/CanvasInspector/CanvasInspector.svelte.d.ts +28 -0
  56. package/dist/components/molecules/CanvasInspector/CanvasInspectorStory.svelte +20 -0
  57. package/dist/components/molecules/CanvasInspector/CanvasInspectorStory.svelte.d.ts +3 -0
  58. package/dist/components/molecules/ColorPicker/ColorPicker.svelte +46 -5
  59. package/dist/components/molecules/ColorPicker/ColorPicker.svelte.d.ts +2 -0
  60. package/dist/components/molecules/ColumnVisibilityMenu/ColumnVisibilityMenu.stories.d.ts +9 -0
  61. package/dist/components/molecules/ColumnVisibilityMenu/ColumnVisibilityMenu.stories.js +8 -0
  62. package/dist/components/molecules/ColumnVisibilityMenu/ColumnVisibilityMenu.svelte +108 -0
  63. package/dist/components/molecules/ColumnVisibilityMenu/ColumnVisibilityMenu.svelte.d.ts +18 -0
  64. package/dist/components/molecules/ColumnVisibilityMenu/ColumnVisibilityMenuStory.svelte +15 -0
  65. package/dist/components/molecules/ColumnVisibilityMenu/ColumnVisibilityMenuStory.svelte.d.ts +3 -0
  66. package/dist/components/molecules/ConflictResolver/ConflictResolver.stories.js +8 -0
  67. package/dist/components/molecules/ConflictResolver/ConflictResolver.svelte +73 -0
  68. package/dist/components/molecules/ConflictResolver/ConflictResolver.svelte.d.ts +16 -0
  69. package/dist/components/molecules/ConflictResolver/ConflictResolverStory.svelte +11 -0
  70. package/dist/components/molecules/ConflictResolver/ConflictResolverStory.svelte.d.ts +18 -0
  71. package/dist/components/molecules/ContextMenu/ContextMenu.svelte +237 -66
  72. package/dist/components/molecules/ContextMenu/ContextMenu.svelte.d.ts +9 -0
  73. package/dist/components/molecules/ExpressionEditor/ExpressionEditor.stories.d.ts +9 -0
  74. package/dist/components/molecules/ExpressionEditor/ExpressionEditor.stories.js +8 -0
  75. package/dist/components/molecules/ExpressionEditor/ExpressionEditor.svelte +56 -0
  76. package/dist/components/molecules/ExpressionEditor/ExpressionEditor.svelte.d.ts +12 -0
  77. package/dist/components/molecules/ExpressionEditor/ExpressionEditorStory.svelte +12 -0
  78. package/dist/components/molecules/ExpressionEditor/ExpressionEditorStory.svelte.d.ts +3 -0
  79. package/dist/components/molecules/FilterList/FilterList.stories.d.ts +9 -0
  80. package/dist/components/molecules/FilterList/FilterList.stories.js +8 -0
  81. package/dist/components/molecules/FilterList/FilterList.svelte +101 -0
  82. package/dist/components/molecules/FilterList/FilterList.svelte.d.ts +18 -0
  83. package/dist/components/molecules/FilterList/FilterListStory.svelte +31 -0
  84. package/dist/components/molecules/FilterList/FilterListStory.svelte.d.ts +3 -0
  85. package/dist/components/molecules/MediaAssetBrowser/MediaAssetBrowser.stories.d.ts +9 -0
  86. package/dist/components/molecules/MediaAssetBrowser/MediaAssetBrowser.stories.js +8 -0
  87. package/dist/components/molecules/MediaAssetBrowser/MediaAssetBrowser.svelte +109 -0
  88. package/dist/components/molecules/MediaAssetBrowser/MediaAssetBrowser.svelte.d.ts +20 -0
  89. package/dist/components/molecules/MediaAssetBrowser/MediaAssetBrowserStory.svelte +18 -0
  90. package/dist/components/molecules/MediaAssetBrowser/MediaAssetBrowserStory.svelte.d.ts +3 -0
  91. package/dist/components/molecules/MediaAssetCard/MediaAssetCard.stories.js +8 -0
  92. package/dist/components/molecules/MediaAssetCard/MediaAssetCard.svelte +50 -0
  93. package/dist/components/molecules/MediaAssetCard/MediaAssetCard.svelte.d.ts +11 -0
  94. package/dist/components/molecules/MediaAssetCard/MediaAssetCardStory.svelte +13 -0
  95. package/dist/components/molecules/MediaAssetCard/MediaAssetCardStory.svelte.d.ts +18 -0
  96. package/dist/components/molecules/MediaLayerItem/MediaLayerItem.stories.js +8 -0
  97. package/dist/components/molecules/MediaLayerItem/MediaLayerItem.svelte +380 -0
  98. package/dist/components/molecules/MediaLayerItem/MediaLayerItem.svelte.d.ts +33 -0
  99. package/dist/components/molecules/MediaLayerItem/MediaLayerItemStory.svelte +14 -0
  100. package/dist/components/molecules/MediaLayerItem/MediaLayerItemStory.svelte.d.ts +18 -0
  101. package/dist/components/molecules/MediaLayerList/MediaLayerList.stories.d.ts +9 -0
  102. package/dist/components/molecules/MediaLayerList/MediaLayerList.stories.js +8 -0
  103. package/dist/components/molecules/MediaLayerList/MediaLayerList.svelte +399 -0
  104. package/dist/components/molecules/MediaLayerList/MediaLayerList.svelte.d.ts +37 -0
  105. package/dist/components/molecules/MediaLayerList/MediaLayerListStory.svelte +24 -0
  106. package/dist/components/molecules/MediaLayerList/MediaLayerListStory.svelte.d.ts +3 -0
  107. package/dist/components/molecules/MediaStage/MediaStage.stories.d.ts +9 -0
  108. package/dist/components/molecules/MediaStage/MediaStage.stories.js +8 -0
  109. package/dist/components/molecules/MediaStage/MediaStage.svelte +1498 -0
  110. package/dist/components/molecules/MediaStage/MediaStage.svelte.d.ts +45 -0
  111. package/dist/components/molecules/MediaStage/MediaStageStory.svelte +35 -0
  112. package/dist/components/molecules/MediaStage/MediaStageStory.svelte.d.ts +3 -0
  113. package/dist/components/molecules/MediaTimeline/MediaTimeline.stories.d.ts +9 -0
  114. package/dist/components/molecules/MediaTimeline/MediaTimeline.stories.js +8 -0
  115. package/dist/components/molecules/MediaTimeline/MediaTimeline.svelte +441 -0
  116. package/dist/components/molecules/MediaTimeline/MediaTimeline.svelte.d.ts +39 -0
  117. package/dist/components/molecules/MediaTimeline/MediaTimelineStory.svelte +20 -0
  118. package/dist/components/molecules/MediaTimeline/MediaTimelineStory.svelte.d.ts +3 -0
  119. package/dist/components/molecules/MixerChannel/MixerChannel.stories.d.ts +9 -0
  120. package/dist/components/molecules/MixerChannel/MixerChannel.stories.js +8 -0
  121. package/dist/components/molecules/MixerChannel/MixerChannel.svelte +92 -0
  122. package/dist/components/molecules/MixerChannel/MixerChannel.svelte.d.ts +11 -0
  123. package/dist/components/molecules/MixerChannel/MixerChannelStory.svelte +13 -0
  124. package/dist/components/molecules/MixerChannel/MixerChannelStory.svelte.d.ts +3 -0
  125. package/dist/components/molecules/NodeGraph/GraphBlueprintNode.svelte +454 -0
  126. package/dist/components/molecules/NodeGraph/GraphBlueprintNode.svelte.d.ts +8 -0
  127. package/dist/components/molecules/NodeGraph/GraphFlowBridge.svelte +26 -0
  128. package/dist/components/molecules/NodeGraph/GraphFlowBridge.svelte.d.ts +22 -0
  129. package/dist/components/molecules/NodeGraph/NodeGraph.stories.d.ts +12 -0
  130. package/dist/components/molecules/NodeGraph/NodeGraph.stories.js +9 -0
  131. package/dist/components/molecules/NodeGraph/NodeGraph.svelte +1409 -0
  132. package/dist/components/molecules/NodeGraph/NodeGraph.svelte.d.ts +33 -0
  133. package/dist/components/molecules/NodeGraph/NodeGraphStory.svelte +90 -0
  134. package/dist/components/molecules/NodeGraph/NodeGraphStory.svelte.d.ts +3 -0
  135. package/dist/components/molecules/NodePalette/NodePalette.stories.js +8 -0
  136. package/dist/components/molecules/NodePalette/NodePalette.svelte +86 -0
  137. package/dist/components/molecules/NodePalette/NodePalette.svelte.d.ts +11 -0
  138. package/dist/components/molecules/NodePalette/NodePaletteStory.svelte +11 -0
  139. package/dist/components/molecules/NodePalette/NodePaletteStory.svelte.d.ts +18 -0
  140. package/dist/components/molecules/PdfViewer/PdfViewer.svelte.d.ts +1 -1
  141. package/dist/components/molecules/Poll/Poll.stories.d.ts +1 -1
  142. package/dist/components/molecules/ProgramMonitor/ProgramMonitor.stories.js +8 -0
  143. package/dist/components/molecules/ProgramMonitor/ProgramMonitor.svelte +794 -0
  144. package/dist/components/molecules/ProgramMonitor/ProgramMonitor.svelte.d.ts +25 -0
  145. package/dist/components/molecules/ProgramMonitor/ProgramMonitorStory.svelte +16 -0
  146. package/dist/components/molecules/ProgramMonitor/ProgramMonitorStory.svelte.d.ts +18 -0
  147. package/dist/components/molecules/PropertyField/PropertyField.svelte +57 -3
  148. package/dist/components/molecules/PropertyField/PropertyField.svelte.d.ts +10 -0
  149. package/dist/components/molecules/PropertyField/PropertyFieldStory.svelte +21 -0
  150. package/dist/components/molecules/PropertyGroup/PropertyGroup.svelte +1 -1
  151. package/dist/components/molecules/QueryBuilder/QueryBuilder.stories.d.ts +9 -0
  152. package/dist/components/molecules/QueryBuilder/QueryBuilder.stories.js +8 -0
  153. package/dist/components/molecules/QueryBuilder/QueryBuilder.svelte +52 -0
  154. package/dist/components/molecules/QueryBuilder/QueryBuilder.svelte.d.ts +18 -0
  155. package/dist/components/molecules/QueryBuilder/QueryBuilderStory.svelte +62 -0
  156. package/dist/components/molecules/QueryBuilder/QueryBuilderStory.svelte.d.ts +3 -0
  157. package/dist/components/molecules/RelationPicker/RelationPicker.stories.d.ts +9 -0
  158. package/dist/components/molecules/RelationPicker/RelationPicker.stories.js +8 -0
  159. package/dist/components/molecules/RelationPicker/RelationPicker.svelte +180 -0
  160. package/dist/components/molecules/RelationPicker/RelationPicker.svelte.d.ts +24 -0
  161. package/dist/components/molecules/RelationPicker/RelationPickerStory.svelte +16 -0
  162. package/dist/components/molecules/RelationPicker/RelationPickerStory.svelte.d.ts +3 -0
  163. package/dist/components/molecules/SchemaFieldBuilder/SchemaFieldBuilder.stories.d.ts +9 -0
  164. package/dist/components/molecules/SchemaFieldBuilder/SchemaFieldBuilder.stories.js +8 -0
  165. package/dist/components/molecules/SchemaFieldBuilder/SchemaFieldBuilder.svelte +154 -0
  166. package/dist/components/molecules/SchemaFieldBuilder/SchemaFieldBuilder.svelte.d.ts +12 -0
  167. package/dist/components/molecules/SchemaFieldBuilder/SchemaFieldBuilderStory.svelte +16 -0
  168. package/dist/components/molecules/SchemaFieldBuilder/SchemaFieldBuilderStory.svelte.d.ts +3 -0
  169. package/dist/components/molecules/SecretField/SecretField.stories.d.ts +9 -0
  170. package/dist/components/molecules/SecretField/SecretField.stories.js +8 -0
  171. package/dist/components/molecules/SecretField/SecretField.svelte +58 -0
  172. package/dist/components/molecules/SecretField/SecretField.svelte.d.ts +15 -0
  173. package/dist/components/molecules/SecretField/SecretFieldStory.svelte +8 -0
  174. package/dist/components/molecules/SecretField/SecretFieldStory.svelte.d.ts +3 -0
  175. package/dist/components/molecules/SplitPane/SplitPane.svelte +99 -40
  176. package/dist/components/molecules/SplitPane/SplitPane.svelte.d.ts +10 -2
  177. package/dist/components/molecules/TableToolbar/TableToolbar.svelte.d.ts +1 -1
  178. package/dist/components/molecules/Terminal/Terminal.stories.js +20 -0
  179. package/dist/components/molecules/Terminal/Terminal.svelte +238 -0
  180. package/dist/components/molecules/Terminal/Terminal.svelte.d.ts +19 -0
  181. package/dist/components/molecules/Terminal/TerminalStory.svelte +47 -0
  182. package/dist/components/molecules/Terminal/TerminalStory.svelte.d.ts +6 -0
  183. package/dist/components/molecules/TimelineClip/TimelineClip.stories.js +8 -0
  184. package/dist/components/molecules/TimelineClip/TimelineClip.svelte +193 -0
  185. package/dist/components/molecules/TimelineClip/TimelineClip.svelte.d.ts +18 -0
  186. package/dist/components/molecules/TimelineClip/TimelineClipStory.svelte +18 -0
  187. package/dist/components/molecules/TimelineClip/TimelineClipStory.svelte.d.ts +18 -0
  188. package/dist/components/molecules/TimelineTrack/TimelineTrack.stories.js +8 -0
  189. package/dist/components/molecules/TimelineTrack/TimelineTrack.svelte +126 -0
  190. package/dist/components/molecules/TimelineTrack/TimelineTrack.svelte.d.ts +27 -0
  191. package/dist/components/molecules/TimelineTrack/TimelineTrackStory.svelte +35 -0
  192. package/dist/components/molecules/TimelineTrack/TimelineTrackStory.svelte.d.ts +18 -0
  193. package/dist/components/molecules/TraceWaterfall/TraceWaterfall.stories.js +8 -0
  194. package/dist/components/molecules/TraceWaterfall/TraceWaterfall.svelte +158 -0
  195. package/dist/components/molecules/TraceWaterfall/TraceWaterfall.svelte.d.ts +18 -0
  196. package/dist/components/molecules/TraceWaterfall/TraceWaterfallStory.svelte +55 -0
  197. package/dist/components/molecules/TraceWaterfall/TraceWaterfallStory.svelte.d.ts +18 -0
  198. package/dist/components/molecules/TrackHeader/TrackHeader.stories.d.ts +9 -0
  199. package/dist/components/molecules/TrackHeader/TrackHeader.stories.js +8 -0
  200. package/dist/components/molecules/TrackHeader/TrackHeader.svelte +54 -0
  201. package/dist/components/molecules/TrackHeader/TrackHeader.svelte.d.ts +9 -0
  202. package/dist/components/molecules/TrackHeader/TrackHeaderStory.svelte +10 -0
  203. package/dist/components/molecules/TrackHeader/TrackHeaderStory.svelte.d.ts +3 -0
  204. package/dist/components/molecules/TransportControls/TransportControls.stories.d.ts +9 -0
  205. package/dist/components/molecules/TransportControls/TransportControls.stories.js +8 -0
  206. package/dist/components/molecules/TransportControls/TransportControls.svelte +135 -0
  207. package/dist/components/molecules/TransportControls/TransportControls.svelte.d.ts +24 -0
  208. package/dist/components/molecules/TransportControls/TransportControlsStory.svelte +40 -0
  209. package/dist/components/molecules/TransportControls/TransportControlsStory.svelte.d.ts +3 -0
  210. package/dist/components/molecules/VersionHistoryPanel/VersionHistoryPanel.stories.js +8 -0
  211. package/dist/components/molecules/VersionHistoryPanel/VersionHistoryPanel.svelte +117 -0
  212. package/dist/components/molecules/VersionHistoryPanel/VersionHistoryPanel.svelte.d.ts +20 -0
  213. package/dist/components/molecules/VersionHistoryPanel/VersionHistoryPanelStory.svelte +36 -0
  214. package/dist/components/molecules/VersionHistoryPanel/VersionHistoryPanelStory.svelte.d.ts +18 -0
  215. package/dist/components/molecules/VideoAnimationsPanel/VideoAnimationsPanel.stories.js +8 -0
  216. package/dist/components/molecules/VideoAnimationsPanel/VideoAnimationsPanel.svelte +213 -0
  217. package/dist/components/molecules/VideoAnimationsPanel/VideoAnimationsPanel.svelte.d.ts +22 -0
  218. package/dist/components/molecules/VideoAnimationsPanel/VideoAnimationsPanelStory.svelte +7 -0
  219. package/dist/components/molecules/VideoAnimationsPanel/VideoAnimationsPanelStory.svelte.d.ts +18 -0
  220. package/dist/components/molecules/VideoComponentsPanel/VideoComponentsPanel.stories.js +8 -0
  221. package/dist/components/molecules/VideoComponentsPanel/VideoComponentsPanel.svelte +524 -0
  222. package/dist/components/molecules/VideoComponentsPanel/VideoComponentsPanel.svelte.d.ts +32 -0
  223. package/dist/components/molecules/VideoComponentsPanel/VideoComponentsPanelStory.svelte +7 -0
  224. package/dist/components/molecules/VideoComponentsPanel/VideoComponentsPanelStory.svelte.d.ts +18 -0
  225. package/dist/components/molecules/VideoPlayer/VideoPlayer.stories.d.ts +1 -1
  226. package/dist/components/molecules/VideoTrackHeader/VideoTrackHeader.stories.d.ts +9 -0
  227. package/dist/components/molecules/VideoTrackHeader/VideoTrackHeader.stories.js +8 -0
  228. package/dist/components/molecules/VideoTrackHeader/VideoTrackHeader.svelte +112 -0
  229. package/dist/components/molecules/VideoTrackHeader/VideoTrackHeader.svelte.d.ts +15 -0
  230. package/dist/components/molecules/VideoTrackHeader/VideoTrackHeaderStory.svelte +10 -0
  231. package/dist/components/molecules/VideoTrackHeader/VideoTrackHeaderStory.svelte.d.ts +3 -0
  232. package/dist/components/molecules/VideoTransitionsPanel/VideoTransitionsPanel.stories.js +8 -0
  233. package/dist/components/molecules/VideoTransitionsPanel/VideoTransitionsPanel.svelte +113 -0
  234. package/dist/components/molecules/VideoTransitionsPanel/VideoTransitionsPanel.svelte.d.ts +18 -0
  235. package/dist/components/molecules/VideoTransitionsPanel/VideoTransitionsPanelStory.svelte +7 -0
  236. package/dist/components/molecules/VideoTransitionsPanel/VideoTransitionsPanelStory.svelte.d.ts +18 -0
  237. package/dist/components/molecules/WaveformRegion/WaveformRegion.stories.js +8 -0
  238. package/dist/components/molecules/WaveformRegion/WaveformRegion.svelte +82 -0
  239. package/dist/components/molecules/WaveformRegion/WaveformRegion.svelte.d.ts +13 -0
  240. package/dist/components/molecules/WaveformRegion/WaveformRegionStory.svelte +17 -0
  241. package/dist/components/molecules/WaveformRegion/WaveformRegionStory.svelte.d.ts +18 -0
  242. package/dist/components/molecules/WidgetCanvas/WidgetCanvas.svelte +13 -4
  243. package/dist/components/molecules/WidgetCanvas/WidgetCanvas.svelte.d.ts +3 -1
  244. package/dist/components/molecules/WidgetCanvas/widgetCanvasContext.d.ts +2 -0
  245. package/dist/components/molecules/WidgetFrame/WidgetFrame.svelte +206 -37
  246. package/dist/components/molecules/WidgetFrame/WidgetFrame.svelte.d.ts +31 -0
  247. package/dist/components/organisms/AudioEditor/AudioEditor.stories.d.ts +12 -0
  248. package/dist/components/organisms/AudioEditor/AudioEditor.stories.js +9 -0
  249. package/dist/components/organisms/AudioEditor/AudioEditor.svelte +324 -0
  250. package/dist/components/organisms/AudioEditor/AudioEditor.svelte.d.ts +13 -0
  251. package/dist/components/organisms/AudioEditor/AudioEditorStory.svelte +10 -0
  252. package/dist/components/organisms/AudioEditor/AudioEditorStory.svelte.d.ts +3 -0
  253. package/dist/components/organisms/BlogEditor/BlogEditor.stories.d.ts +12 -0
  254. package/dist/components/organisms/BlogEditor/BlogEditor.stories.js +9 -0
  255. package/dist/components/organisms/BlogEditor/BlogEditor.svelte +1208 -0
  256. package/dist/components/organisms/BlogEditor/BlogEditor.svelte.d.ts +16 -0
  257. package/dist/components/organisms/BlogEditor/BlogEditorStory.svelte +144 -0
  258. package/dist/components/organisms/BlogEditor/BlogEditorStory.svelte.d.ts +3 -0
  259. package/dist/components/organisms/BlogEditor/DemoBlogCard.svelte +28 -0
  260. package/dist/components/organisms/BlogEditor/DemoBlogCard.svelte.d.ts +10 -0
  261. package/dist/components/organisms/BlogEditor/DemoBlogStats.svelte +34 -0
  262. package/dist/components/organisms/BlogEditor/DemoBlogStats.svelte.d.ts +11 -0
  263. package/dist/components/organisms/BlogEditor/DemoBlogWidget.svelte +13 -0
  264. package/dist/components/organisms/BlogEditor/DemoBlogWidget.svelte.d.ts +8 -0
  265. package/dist/components/organisms/BlogRenderer/BlogRenderer.stories.js +8 -0
  266. package/dist/components/organisms/BlogRenderer/BlogRenderer.svelte +469 -0
  267. package/dist/components/organisms/BlogRenderer/BlogRenderer.svelte.d.ts +14 -0
  268. package/dist/components/organisms/BlogRenderer/BlogRendererStory.svelte +20 -0
  269. package/dist/components/organisms/BlogRenderer/BlogRendererStory.svelte.d.ts +18 -0
  270. package/dist/components/organisms/BlueprintEditor/BlueprintEditor.stories.d.ts +12 -0
  271. package/dist/components/organisms/BlueprintEditor/BlueprintEditor.stories.js +9 -0
  272. package/dist/components/organisms/BlueprintEditor/BlueprintEditor.svelte +1012 -0
  273. package/dist/components/organisms/BlueprintEditor/BlueprintEditor.svelte.d.ts +16 -0
  274. package/dist/components/organisms/BlueprintEditor/BlueprintEditorStory.svelte +76 -0
  275. package/dist/components/organisms/BlueprintEditor/BlueprintEditorStory.svelte.d.ts +3 -0
  276. package/dist/components/organisms/CanvasEditor/CanvasEditor.stories.d.ts +12 -0
  277. package/dist/components/organisms/CanvasEditor/CanvasEditor.stories.js +9 -0
  278. package/dist/components/organisms/CanvasEditor/CanvasEditor.svelte +1680 -0
  279. package/dist/components/organisms/CanvasEditor/CanvasEditor.svelte.d.ts +18 -0
  280. package/dist/components/organisms/CanvasEditor/CanvasEditorStory.svelte +329 -0
  281. package/dist/components/organisms/CanvasEditor/CanvasEditorStory.svelte.d.ts +3 -0
  282. package/dist/components/organisms/DashboardBuilderPage/DashboardBuilderPage.svelte.d.ts +1 -1
  283. package/dist/components/organisms/DesktopShell/DesktopShell.svelte.d.ts +1 -1
  284. package/dist/components/organisms/EditorShell/EditorShell.svelte +162 -57
  285. package/dist/components/organisms/EditorShell/EditorShell.svelte.d.ts +21 -1
  286. package/dist/components/organisms/FileUploader/FileUploader.stories.d.ts +10 -0
  287. package/dist/components/organisms/FileUploader/FileUploader.stories.js +21 -0
  288. package/dist/components/organisms/FileUploader/FileUploader.svelte +127 -25
  289. package/dist/components/organisms/FileUploader/FileUploader.svelte.d.ts +20 -0
  290. package/dist/components/organisms/FileUploader/FileUploaderStory.svelte +7 -1
  291. package/dist/components/organisms/FileUploader/FileUploaderStory.svelte.d.ts +3 -0
  292. package/dist/components/organisms/ImportWizard/ImportWizard.stories.js +8 -0
  293. package/dist/components/organisms/ImportWizard/ImportWizard.svelte +209 -0
  294. package/dist/components/organisms/ImportWizard/ImportWizard.svelte.d.ts +22 -0
  295. package/dist/components/organisms/ImportWizard/ImportWizardStory.svelte +16 -0
  296. package/dist/components/organisms/ImportWizard/ImportWizardStory.svelte.d.ts +18 -0
  297. package/dist/components/organisms/VideoEditor/VideoEditor.stories.d.ts +12 -0
  298. package/dist/components/organisms/VideoEditor/VideoEditor.stories.js +9 -0
  299. package/dist/components/organisms/VideoEditor/VideoEditor.svelte +1687 -0
  300. package/dist/components/organisms/VideoEditor/VideoEditor.svelte.d.ts +14 -0
  301. package/dist/components/organisms/VideoEditor/VideoEditorStory.svelte +11 -0
  302. package/dist/components/organisms/VideoEditor/VideoEditorStory.svelte.d.ts +3 -0
  303. package/dist/components/templates/AudioEditorTemplate/AudioEditorTemplate.stories.d.ts +12 -0
  304. package/dist/components/templates/AudioEditorTemplate/AudioEditorTemplate.stories.js +9 -0
  305. package/dist/components/templates/AudioEditorTemplate/AudioEditorTemplate.svelte +22 -0
  306. package/dist/components/templates/AudioEditorTemplate/AudioEditorTemplate.svelte.d.ts +13 -0
  307. package/dist/components/templates/AudioEditorTemplate/AudioEditorTemplateStory.svelte +8 -0
  308. package/dist/components/templates/AudioEditorTemplate/AudioEditorTemplateStory.svelte.d.ts +3 -0
  309. package/dist/components/templates/CanvasEditorTemplate/CanvasEditorTemplate.stories.d.ts +12 -0
  310. package/dist/components/templates/CanvasEditorTemplate/CanvasEditorTemplate.stories.js +9 -0
  311. package/dist/components/templates/CanvasEditorTemplate/CanvasEditorTemplate.svelte +32 -0
  312. package/dist/components/templates/CanvasEditorTemplate/CanvasEditorTemplate.svelte.d.ts +17 -0
  313. package/dist/components/templates/CanvasEditorTemplate/CanvasEditorTemplateStory.svelte +21 -0
  314. package/dist/components/templates/CanvasEditorTemplate/CanvasEditorTemplateStory.svelte.d.ts +3 -0
  315. package/dist/components/templates/VideoEditorTemplate/VideoEditorTemplate.stories.d.ts +12 -0
  316. package/dist/components/templates/VideoEditorTemplate/VideoEditorTemplate.stories.js +9 -0
  317. package/dist/components/templates/VideoEditorTemplate/VideoEditorTemplate.svelte +22 -0
  318. package/dist/components/templates/VideoEditorTemplate/VideoEditorTemplate.svelte.d.ts +13 -0
  319. package/dist/components/templates/VideoEditorTemplate/VideoEditorTemplateStory.svelte +8 -0
  320. package/dist/components/templates/VideoEditorTemplate/VideoEditorTemplateStory.svelte.d.ts +3 -0
  321. package/dist/index.d.ts +91 -1
  322. package/dist/index.js +64 -0
  323. package/dist/types/xyflow-svelte.d.ts +62 -0
  324. package/dist/utils/audioProject.d.ts +19 -0
  325. package/dist/utils/audioProject.js +70 -0
  326. package/dist/utils/blogDocument.d.ts +175 -0
  327. package/dist/utils/blogDocument.js +220 -0
  328. package/dist/utils/blueprintRuntime.d.ts +34 -0
  329. package/dist/utils/blueprintRuntime.js +289 -0
  330. package/dist/utils/canvasDocument.d.ts +239 -0
  331. package/dist/utils/canvasDocument.js +443 -0
  332. package/dist/utils/canvasExport.d.ts +10 -0
  333. package/dist/utils/canvasExport.js +469 -0
  334. package/dist/utils/canvasHierarchy.d.ts +189 -0
  335. package/dist/utils/canvasHierarchy.js +674 -0
  336. package/dist/utils/canvasHistory.d.ts +19 -0
  337. package/dist/utils/canvasHistory.js +48 -0
  338. package/dist/utils/canvasWidget.d.ts +81 -0
  339. package/dist/utils/canvasWidget.js +597 -0
  340. package/dist/utils/mediaTime.d.ts +26 -0
  341. package/dist/utils/mediaTime.js +76 -0
  342. package/dist/utils/mediaTracks.d.ts +215 -0
  343. package/dist/utils/mediaTracks.js +798 -0
  344. package/dist/utils/nodeGraph.d.ts +354 -0
  345. package/dist/utils/nodeGraph.js +1453 -0
  346. package/dist/utils/queryBridge.d.ts +18 -0
  347. package/dist/utils/queryBridge.js +118 -0
  348. package/dist/utils/videoSequence.d.ts +13 -0
  349. package/dist/utils/videoSequence.js +94 -0
  350. package/package.json +5 -2
@@ -0,0 +1,1140 @@
1
+ <script lang="ts">
2
+ import PropertyGroup from '../PropertyGroup/PropertyGroup.svelte';
3
+ import PropertyField from '../PropertyField/PropertyField.svelte';
4
+ import Input from '../../atoms/Input/Input.svelte';
5
+ import Textarea from '../../atoms/Textarea/Textarea.svelte';
6
+ import Select from '../Select/Select.svelte';
7
+ import Slider from '../../atoms/Slider/Slider.svelte';
8
+ import Toggle from '../../atoms/Toggle/Toggle.svelte';
9
+ import IconButton from '../../atoms/IconButton/IconButton.svelte';
10
+ import Tooltip from '../../atoms/Tooltip/Tooltip.svelte';
11
+ import ColorPicker from '../ColorPicker/ColorPicker.svelte';
12
+ import FileUploader from '../../organisms/FileUploader/FileUploader.svelte';
13
+ import {
14
+ alignLayerRect,
15
+ isCanvasFieldModified,
16
+ resetCanvasField,
17
+ type CanvasAlign,
18
+ type CanvasDocument,
19
+ type CanvasExposedProp,
20
+ type CanvasLayer,
21
+ type CanvasResettableField,
22
+ type CanvasWidgetDefinition
23
+ } from '../../../utils/canvasDocument.js';
24
+ import {
25
+ ANCHOR_PRESETS,
26
+ LAYOUT_BOX_KINDS,
27
+ computeAbsoluteRects,
28
+ contentPadding,
29
+ isContainerKind,
30
+ slotFromLocalRect,
31
+ syncSlotFromRect
32
+ } from '../../../utils/canvasHierarchy.js';
33
+ import {
34
+ groupExposedPropsByLayer,
35
+ isPropExposed,
36
+ listFillableSlotsForInstance,
37
+ resolveExposedPropValue
38
+ } from '../../../utils/canvasWidget.js';
39
+ import type { Component } from 'svelte';
40
+ import FlipHorizontal2 from '@lucide/svelte/icons/flip-horizontal-2';
41
+ import FlipVertical2 from '@lucide/svelte/icons/flip-vertical-2';
42
+ import AlignStartVertical from '@lucide/svelte/icons/align-start-vertical';
43
+ import AlignCenterVertical from '@lucide/svelte/icons/align-center-vertical';
44
+ import AlignEndVertical from '@lucide/svelte/icons/align-end-vertical';
45
+ import AlignStartHorizontal from '@lucide/svelte/icons/align-start-horizontal';
46
+ import AlignCenterHorizontal from '@lucide/svelte/icons/align-center-horizontal';
47
+ import AlignEndHorizontal from '@lucide/svelte/icons/align-end-horizontal';
48
+ import AlignCenter from '@lucide/svelte/icons/align-center';
49
+ import Maximize2 from '@lucide/svelte/icons/maximize-2';
50
+
51
+ type IconComp = Component<{ class?: string }>;
52
+
53
+ interface CanvasInspectorProps {
54
+ document?: CanvasDocument | null;
55
+ layer?: CanvasLayer | null;
56
+ selectionCount?: number;
57
+ /** When editing inside a User Widget definition — enables eye toggles. */
58
+ widgetDefinition?: CanvasWidgetDefinition | null;
59
+ class?: string;
60
+ ondocumentchange?: (doc: CanvasDocument) => void;
61
+ onchange?: (layer: CanvasLayer) => void;
62
+ onalign?: (align: CanvasAlign) => void;
63
+ onexpose?: (payload: { layerId: string; field: string; exposed: boolean; label: string }) => void;
64
+ onoverride?: (payload: { propId: string; value: unknown }) => void;
65
+ oneditwidget?: (definitionId: string) => void;
66
+ onbreakwidget?: () => void;
67
+ }
68
+
69
+ let {
70
+ document: doc = null,
71
+ layer = null,
72
+ selectionCount = 0,
73
+ widgetDefinition = null,
74
+ class: className = '',
75
+ ondocumentchange,
76
+ onchange,
77
+ onalign,
78
+ onexpose,
79
+ onoverride,
80
+ oneditwidget,
81
+ onbreakwidget
82
+ }: CanvasInspectorProps = $props();
83
+
84
+ const exposeMode = $derived(!!widgetDefinition);
85
+ const instanceDef = $derived(
86
+ layer?.kind === 'widget' && layer.definitionId
87
+ ? (doc?.widgets ?? []).find((w) => w.id === layer.definitionId) ?? null
88
+ : null
89
+ );
90
+ const exposedGroups = $derived(instanceDef ? groupExposedPropsByLayer(instanceDef) : []);
91
+
92
+ function exposedValue(prop: CanvasExposedProp): unknown {
93
+ if (!layer || !instanceDef) return undefined;
94
+ return resolveExposedPropValue(layer, instanceDef, prop);
95
+ }
96
+
97
+ /** Parent content box used for slot ↔ rect sync (local X/Y). */
98
+ const parentContentSize = $derived.by((): { width: number; height: number } => {
99
+ if (!doc) return { width: 1, height: 1 };
100
+ const parentId = layer?.parentId ?? null;
101
+ if (!parentId) return { width: doc.width, height: doc.height };
102
+ const absMap = computeAbsoluteRects(doc.layers, { width: doc.width, height: doc.height });
103
+ const parent = doc.layers.find((l) => l.id === parentId);
104
+ const parentAbs = absMap.get(parentId);
105
+ if (!parent || !parentAbs) return { width: doc.width, height: doc.height };
106
+ const pad = contentPadding(parent);
107
+ return {
108
+ width: Math.max(1, parentAbs.w - pad.left - pad.right),
109
+ height: Math.max(1, parentAbs.h - pad.top - pad.bottom)
110
+ };
111
+ });
112
+
113
+ const parentLayoutLocked = $derived.by(() => {
114
+ if (!doc || !layer?.parentId) return false;
115
+ const parent = doc.layers.find((l) => l.id === layer.parentId);
116
+ return !!parent && LAYOUT_BOX_KINDS.has(parent.kind);
117
+ });
118
+
119
+ function exposedFlag(field: string): boolean | null {
120
+ if (!exposeMode || !layer || !widgetDefinition) return null;
121
+ return isPropExposed(widgetDefinition, layer.id, field);
122
+ }
123
+
124
+ function toggleExpose(field: string, label: string, next: boolean) {
125
+ if (!layer) return;
126
+ onexpose?.({ layerId: layer.id, field, exposed: next, label });
127
+ }
128
+
129
+ const fitOptions = [
130
+ { value: 'cover', label: 'Cover' },
131
+ { value: 'contain', label: 'Contain' },
132
+ { value: 'fill', label: 'Fill' }
133
+ ];
134
+ const weightOptions = [
135
+ { value: '400', label: 'Regular' },
136
+ { value: '500', label: 'Medium' },
137
+ { value: '600', label: 'Semibold' },
138
+ { value: '700', label: 'Bold' },
139
+ { value: '800', label: 'Extra bold' }
140
+ ];
141
+ const alignOptions = [
142
+ { value: 'left', label: 'Left' },
143
+ { value: 'center', label: 'Center' },
144
+ { value: 'right', label: 'Right' }
145
+ ];
146
+ const styleOptions = [
147
+ { value: 'normal', label: 'Normal' },
148
+ { value: 'italic', label: 'Italic' }
149
+ ];
150
+ const decoOptions = [
151
+ { value: 'none', label: 'None' },
152
+ { value: 'underline', label: 'Underline' },
153
+ { value: 'line-through', label: 'Strike' }
154
+ ];
155
+ const shapeKinds = [
156
+ 'rect',
157
+ 'roundRect',
158
+ 'ellipse',
159
+ 'triangle',
160
+ 'star',
161
+ 'hexagon',
162
+ 'pentagon',
163
+ 'diamond',
164
+ 'heart',
165
+ 'line',
166
+ 'arrow',
167
+ 'sticky',
168
+ 'border'
169
+ ];
170
+
171
+ const anchorOptions = [
172
+ { value: 'topLeft', label: 'Top left' },
173
+ { value: 'topCenter', label: 'Top center' },
174
+ { value: 'topRight', label: 'Top right' },
175
+ { value: 'centerLeft', label: 'Center left' },
176
+ { value: 'center', label: 'Center' },
177
+ { value: 'centerRight', label: 'Center right' },
178
+ { value: 'bottomLeft', label: 'Bottom left' },
179
+ { value: 'bottomCenter', label: 'Bottom center' },
180
+ { value: 'bottomRight', label: 'Bottom right' },
181
+ { value: 'stretch', label: 'Stretch' },
182
+ { value: 'stretchHorizontal', label: 'Stretch H' },
183
+ { value: 'stretchVertical', label: 'Stretch V' }
184
+ ];
185
+
186
+ const sizeRuleOptions = [
187
+ { value: 'fixed', label: 'Fixed' },
188
+ { value: 'fill', label: 'Fill' }
189
+ ];
190
+
191
+ const alignAxisOptions = [
192
+ { value: '0', label: 'Start' },
193
+ { value: '0.5', label: 'Center' },
194
+ { value: '1', label: 'End' }
195
+ ];
196
+
197
+ const parentKind = $derived(
198
+ layer?.parentId && doc
199
+ ? (doc.layers.find((l) => l.id === layer.parentId)?.kind ?? null)
200
+ : null
201
+ );
202
+ const showChildAlignment = $derived(
203
+ parentKind === 'hBox' || parentKind === 'vBox'
204
+ );
205
+ const showContainerPadding = $derived(
206
+ !!layer && (isContainerKind(layer.kind) || layer.kind === 'widget')
207
+ );
208
+
209
+ function currentAnchorPreset(): string {
210
+ const a = layer?.slot?.anchors;
211
+ if (!a) return 'topLeft';
212
+ for (const [key, val] of Object.entries(ANCHOR_PRESETS)) {
213
+ if (
214
+ val.minX === a.minX &&
215
+ val.minY === a.minY &&
216
+ val.maxX === a.maxX &&
217
+ val.maxY === a.maxY
218
+ ) {
219
+ return key;
220
+ }
221
+ }
222
+ return 'topLeft';
223
+ }
224
+
225
+ function setAnchorPreset(id: string) {
226
+ if (!layer) return;
227
+ const anchors = ANCHOR_PRESETS[id as keyof typeof ANCHOR_PRESETS];
228
+ if (!anchors) return;
229
+ const size = parentContentSize;
230
+ const next = syncSlotFromRect(
231
+ {
232
+ ...layer,
233
+ slot: {
234
+ ...(layer.slot ?? slotFromLocalRect(size, layer.rect, anchors)),
235
+ anchors: { ...anchors }
236
+ }
237
+ },
238
+ size
239
+ );
240
+ onchange?.(next);
241
+ }
242
+
243
+ const alignDock: { id: CanvasAlign; label: string; icon: IconComp }[] = [
244
+ { id: 'left', label: 'Align left', icon: AlignStartVertical },
245
+ { id: 'center-h', label: 'Align center', icon: AlignCenterVertical },
246
+ { id: 'right', label: 'Align right', icon: AlignEndVertical },
247
+ { id: 'top', label: 'Align top', icon: AlignStartHorizontal },
248
+ { id: 'center-v', label: 'Align middle', icon: AlignCenterHorizontal },
249
+ { id: 'bottom', label: 'Align bottom', icon: AlignEndHorizontal },
250
+ { id: 'center', label: 'Center on canvas', icon: AlignCenter },
251
+ { id: 'full', label: 'Fill canvas', icon: Maximize2 }
252
+ ];
253
+
254
+ function patchDoc(partial: Partial<CanvasDocument>) {
255
+ if (!doc) return;
256
+ ondocumentchange?.({ ...doc, ...partial });
257
+ }
258
+
259
+ function patch(partial: Partial<CanvasLayer>) {
260
+ if (!layer) return;
261
+ onchange?.({ ...layer, ...partial });
262
+ }
263
+
264
+ function fieldModified(field: CanvasResettableField): boolean {
265
+ return !!layer && isCanvasFieldModified(layer, field);
266
+ }
267
+
268
+ function resetField(field: CanvasResettableField) {
269
+ if (!layer) return;
270
+ patch(resetCanvasField(layer, field));
271
+ }
272
+
273
+ function patchRect(partial: Partial<CanvasLayer['rect']>) {
274
+ if (!layer || !doc) return;
275
+ const rect = { ...layer.rect, ...partial };
276
+ onchange?.(syncSlotFromRect({ ...layer, rect }, parentContentSize));
277
+ }
278
+
279
+ function applyAlign(align: CanvasAlign) {
280
+ if (onalign) {
281
+ onalign(align);
282
+ return;
283
+ }
284
+ if (!layer || !doc) return;
285
+ patch({
286
+ rect: alignLayerRect(layer.rect, { width: doc.width, height: doc.height }, align)
287
+ });
288
+ }
289
+
290
+ function replaceMedia(files: File[]) {
291
+ const file = files[0];
292
+ if (!file || !layer) return;
293
+ const src = URL.createObjectURL(file);
294
+ const kind = file.type.startsWith('video/')
295
+ ? 'video'
296
+ : layer.kind === 'video'
297
+ ? 'video'
298
+ : 'image';
299
+ patch({ src, name: file.name, kind });
300
+ }
301
+ </script>
302
+
303
+ <div class={['min-w-0', className]}>
304
+ {#if selectionCount > 1}
305
+ <p class="px-3 py-6 text-center text-xs text-muted">
306
+ {selectionCount} layers selected — use the bulk dock
307
+ </p>
308
+ {:else if !layer}
309
+ <p class="px-3 py-6 text-center text-xs text-muted">Select a layer to edit</p>
310
+ {:else}
311
+ <PropertyGroup title="Layer">
312
+ <PropertyField
313
+ label="Name"
314
+ modified={fieldModified('name')}
315
+ onreset={() => resetField('name')}
316
+ >
317
+ <Input
318
+ size="sm"
319
+ value={layer.name}
320
+ oninput={(e) => patch({ name: (e.currentTarget as HTMLInputElement).value })}
321
+ />
322
+ </PropertyField>
323
+ <PropertyField
324
+ label="Visible"
325
+ exposed={exposedFlag('visible')}
326
+ onexpose={(v) => toggleExpose('visible', 'Visible', v)}
327
+ modified={fieldModified('visible')}
328
+ onreset={() => resetField('visible')}
329
+ >
330
+ <Toggle
331
+ checked={layer.visible}
332
+ onchange={(v) => patch({ visible: v })}
333
+ size="sm"
334
+ />
335
+ </PropertyField>
336
+ <PropertyField
337
+ label="Locked"
338
+ modified={fieldModified('locked')}
339
+ onreset={() => resetField('locked')}
340
+ >
341
+ <Toggle checked={layer.locked} onchange={(v) => patch({ locked: v })} size="sm" />
342
+ </PropertyField>
343
+ <PropertyField
344
+ label="Opacity"
345
+ exposed={exposedFlag('opacity')}
346
+ onexpose={(v) => toggleExpose('opacity', 'Opacity', v)}
347
+ modified={fieldModified('opacity')}
348
+ onreset={() => resetField('opacity')}
349
+ >
350
+ <Slider
351
+ size="sm"
352
+ min={0}
353
+ max={1}
354
+ step={0.01}
355
+ value={layer.opacity}
356
+ showValue
357
+ valuePosition="header"
358
+ oninput={(v) => patch({ opacity: v })}
359
+ />
360
+ </PropertyField>
361
+ </PropertyGroup>
362
+
363
+ {#if instanceDef && layer.kind === 'widget'}
364
+ <PropertyGroup title="Widget · {instanceDef.name}">
365
+ {#each exposedGroups as group (group.layerId)}
366
+ <div class="space-y-0.5 border-b border-border/60 py-1 last:border-b-0">
367
+ <p
368
+ class="px-2 pt-0.5 text-[10px] font-semibold uppercase tracking-wide text-muted"
369
+ title="Blueprint layer"
370
+ >
371
+ {group.layerName}
372
+ </p>
373
+ {#each group.props as prop (prop.id)}
374
+ {@const current = exposedValue(prop)}
375
+ {@const hasOverride = layer.overrides != null && prop.id in layer.overrides}
376
+ <PropertyField
377
+ label={prop.label}
378
+ modified={hasOverride}
379
+ onreset={() => onoverride?.({ propId: prop.id, value: undefined })}
380
+ >
381
+ {#if prop.field === 'visible'}
382
+ <Toggle
383
+ checked={Boolean(current ?? true)}
384
+ onchange={(v) => onoverride?.({ propId: prop.id, value: v })}
385
+ size="sm"
386
+ />
387
+ {:else if prop.field === 'opacity' || prop.field === 'fontSize' || prop.field === 'borderRadius' || prop.field === 'strokeWidth'}
388
+ <Input
389
+ type="number"
390
+ size="sm"
391
+ value={current == null || current === '' ? '' : String(current)}
392
+ oninput={(e) =>
393
+ onoverride?.({
394
+ propId: prop.id,
395
+ value: Number((e.currentTarget as HTMLInputElement).value)
396
+ })}
397
+ />
398
+ {:else if prop.field === 'fill' || prop.field === 'color' || prop.field === 'stroke' || prop.field === 'textBackground'}
399
+ <ColorPicker
400
+ value={String(current ?? '#000000')}
401
+ showSwatches={false}
402
+ onchange={(v) => onoverride?.({ propId: prop.id, value: v })}
403
+ />
404
+ {:else}
405
+ <Input
406
+ size="sm"
407
+ value={String(current ?? '')}
408
+ oninput={(e) =>
409
+ onoverride?.({
410
+ propId: prop.id,
411
+ value: (e.currentTarget as HTMLInputElement).value
412
+ })}
413
+ />
414
+ {/if}
415
+ </PropertyField>
416
+ {/each}
417
+ </div>
418
+ {:else}
419
+ <p class="px-2 py-2 text-[11px] text-muted">
420
+ No exposed properties — edit the widget and use the eye icon on fields
421
+ </p>
422
+ {/each}
423
+ <div class="flex flex-col gap-1 px-1 py-1">
424
+ <button
425
+ type="button"
426
+ class="rounded-md border border-border px-2 py-1.5 text-xs hover:bg-surface-overlay"
427
+ onclick={() => layer.definitionId && oneditwidget?.(layer.definitionId)}
428
+ >
429
+ Edit widget blueprint
430
+ </button>
431
+ <button
432
+ type="button"
433
+ class="rounded-md border border-border px-2 py-1.5 text-xs text-danger hover:bg-surface-overlay"
434
+ onclick={() => onbreakwidget?.()}
435
+ >
436
+ Break instance
437
+ </button>
438
+ </div>
439
+ </PropertyGroup>
440
+ {/if}
441
+
442
+ <PropertyGroup title="Slot">
443
+ {#if layer.kind === 'namedSlot'}
444
+ <PropertyField label="Slot name">
445
+ <Input
446
+ size="sm"
447
+ value={layer.slotName ?? layer.name}
448
+ oninput={(e) => {
449
+ const v = (e.currentTarget as HTMLInputElement).value;
450
+ patch({ slotName: v, name: layer.name === (layer.slotName ?? layer.name) ? v : layer.name });
451
+ }}
452
+ />
453
+ </PropertyField>
454
+ {/if}
455
+ {#if layer.parentId && doc?.layers.find((l) => l.id === layer.parentId)?.kind === 'widget'}
456
+ {@const parentWidget = doc.layers.find((l) => l.id === layer.parentId)}
457
+ {@const slots = listFillableSlotsForInstance(doc, parentWidget?.id ?? '')}
458
+ <PropertyField label="Fill slot">
459
+ <Select
460
+ size="sm"
461
+ options={[
462
+ { value: '', label: 'Host (default)' },
463
+ ...slots.map((s) => ({ value: s, label: s }))
464
+ ]}
465
+ value={layer.fillSlot ?? ''}
466
+ onchange={(v) => patch({ fillSlot: v || undefined })}
467
+ />
468
+ </PropertyField>
469
+ {/if}
470
+ <PropertyField label="Anchors">
471
+ <Select
472
+ size="sm"
473
+ options={anchorOptions}
474
+ value={currentAnchorPreset()}
475
+ onchange={(v) => setAnchorPreset(v)}
476
+ />
477
+ </PropertyField>
478
+ <p class="px-1 pb-1 text-[10px] leading-snug text-muted">
479
+ Cómo se sujeta al padre al redimensionarlo: esquina fija, centro, o Stretch para
480
+ estirarse con el contenedor (como UMG).
481
+ </p>
482
+ <PropertyField label="Size rule">
483
+ <Select
484
+ size="sm"
485
+ options={sizeRuleOptions}
486
+ value={layer.slot?.sizeRule === 'auto' ? 'fixed' : (layer.slot?.sizeRule ?? 'fixed')}
487
+ onchange={(v) =>
488
+ patch({
489
+ slot: {
490
+ ...(layer.slot ?? {
491
+ anchors: { minX: 0, minY: 0, maxX: 0, maxY: 0 },
492
+ offsets: { left: 0, top: 0, right: 0, bottom: 0 }
493
+ }),
494
+ sizeRule: v as 'fill' | 'fixed'
495
+ }
496
+ })}
497
+ />
498
+ </PropertyField>
499
+ {#if showChildAlignment}
500
+ <div class="grid grid-cols-2 gap-2">
501
+ <PropertyField label={parentKind === 'hBox' ? 'Align Y' : 'Align X'}>
502
+ <Select
503
+ size="sm"
504
+ options={alignAxisOptions}
505
+ value={String(
506
+ parentKind === 'hBox'
507
+ ? (layer.slot?.alignment?.y ?? 0)
508
+ : (layer.slot?.alignment?.x ?? 0)
509
+ )}
510
+ onchange={(v) => {
511
+ const n = Number(v);
512
+ const alignment =
513
+ parentKind === 'hBox'
514
+ ? { x: layer.slot?.alignment?.x ?? 0, y: n }
515
+ : { x: n, y: layer.slot?.alignment?.y ?? 0 };
516
+ patch({
517
+ slot: {
518
+ ...(layer.slot ?? {
519
+ anchors: { minX: 0, minY: 0, maxX: 0, maxY: 0 },
520
+ offsets: { left: 0, top: 0, right: 0, bottom: 0 }
521
+ }),
522
+ alignment
523
+ }
524
+ });
525
+ }}
526
+ />
527
+ </PropertyField>
528
+ </div>
529
+ {/if}
530
+ {#if showContainerPadding}
531
+ <div class="grid grid-cols-2 gap-2">
532
+ <PropertyField label="Pad L">
533
+ <Input
534
+ type="number"
535
+ size="sm"
536
+ value={String(layer.slot?.padding?.left ?? 0)}
537
+ oninput={(e) => {
538
+ const left = Number((e.currentTarget as HTMLInputElement).value) || 0;
539
+ patch({
540
+ slot: {
541
+ ...(layer.slot ?? {
542
+ anchors: { minX: 0, minY: 0, maxX: 0, maxY: 0 },
543
+ offsets: { left: 0, top: 0, right: 0, bottom: 0 }
544
+ }),
545
+ padding: {
546
+ left,
547
+ top: layer.slot?.padding?.top ?? 0,
548
+ right: layer.slot?.padding?.right ?? 0,
549
+ bottom: layer.slot?.padding?.bottom ?? 0
550
+ }
551
+ }
552
+ });
553
+ }}
554
+ />
555
+ </PropertyField>
556
+ <PropertyField label="Pad T">
557
+ <Input
558
+ type="number"
559
+ size="sm"
560
+ value={String(layer.slot?.padding?.top ?? 0)}
561
+ oninput={(e) => {
562
+ const top = Number((e.currentTarget as HTMLInputElement).value) || 0;
563
+ patch({
564
+ slot: {
565
+ ...(layer.slot ?? {
566
+ anchors: { minX: 0, minY: 0, maxX: 0, maxY: 0 },
567
+ offsets: { left: 0, top: 0, right: 0, bottom: 0 }
568
+ }),
569
+ padding: {
570
+ left: layer.slot?.padding?.left ?? 0,
571
+ top,
572
+ right: layer.slot?.padding?.right ?? 0,
573
+ bottom: layer.slot?.padding?.bottom ?? 0
574
+ }
575
+ }
576
+ });
577
+ }}
578
+ />
579
+ </PropertyField>
580
+ <PropertyField label="Pad R">
581
+ <Input
582
+ type="number"
583
+ size="sm"
584
+ value={String(layer.slot?.padding?.right ?? 0)}
585
+ oninput={(e) => {
586
+ const right = Number((e.currentTarget as HTMLInputElement).value) || 0;
587
+ patch({
588
+ slot: {
589
+ ...(layer.slot ?? {
590
+ anchors: { minX: 0, minY: 0, maxX: 0, maxY: 0 },
591
+ offsets: { left: 0, top: 0, right: 0, bottom: 0 }
592
+ }),
593
+ padding: {
594
+ left: layer.slot?.padding?.left ?? 0,
595
+ top: layer.slot?.padding?.top ?? 0,
596
+ right,
597
+ bottom: layer.slot?.padding?.bottom ?? 0
598
+ }
599
+ }
600
+ });
601
+ }}
602
+ />
603
+ </PropertyField>
604
+ <PropertyField label="Pad B">
605
+ <Input
606
+ type="number"
607
+ size="sm"
608
+ value={String(layer.slot?.padding?.bottom ?? 0)}
609
+ oninput={(e) => {
610
+ const bottom = Number((e.currentTarget as HTMLInputElement).value) || 0;
611
+ patch({
612
+ slot: {
613
+ ...(layer.slot ?? {
614
+ anchors: { minX: 0, minY: 0, maxX: 0, maxY: 0 },
615
+ offsets: { left: 0, top: 0, right: 0, bottom: 0 }
616
+ }),
617
+ padding: {
618
+ left: layer.slot?.padding?.left ?? 0,
619
+ top: layer.slot?.padding?.top ?? 0,
620
+ right: layer.slot?.padding?.right ?? 0,
621
+ bottom
622
+ }
623
+ }
624
+ });
625
+ }}
626
+ />
627
+ </PropertyField>
628
+ </div>
629
+ {/if}
630
+ <PropertyField
631
+ label="Clip children"
632
+ modified={fieldModified('clipChildren')}
633
+ onreset={() => resetField('clipChildren')}
634
+ >
635
+ <Toggle
636
+ checked={!!layer.clipChildren || layer.kind === 'scrollBox'}
637
+ onchange={(v) => patch({ clipChildren: v })}
638
+ size="sm"
639
+ />
640
+ </PropertyField>
641
+ {#if layer.kind === 'hBox' || layer.kind === 'vBox' || layer.kind === 'wrapBox' || layer.kind === 'uniformGrid'}
642
+ <PropertyField
643
+ label="Gap"
644
+ modified={fieldModified('gap')}
645
+ onreset={() => resetField('gap')}
646
+ >
647
+ <Input
648
+ type="number"
649
+ size="sm"
650
+ value={String(layer.gap ?? 0)}
651
+ oninput={(e) =>
652
+ patch({ gap: Number((e.currentTarget as HTMLInputElement).value) })}
653
+ />
654
+ </PropertyField>
655
+ {/if}
656
+ {#if layer.kind === 'uniformGrid'}
657
+ <PropertyField
658
+ label="Columns"
659
+ modified={fieldModified('columns')}
660
+ onreset={() => resetField('columns')}
661
+ >
662
+ <Input
663
+ type="number"
664
+ size="sm"
665
+ min={1}
666
+ value={String(layer.columns ?? 2)}
667
+ oninput={(e) =>
668
+ patch({ columns: Math.max(1, Number((e.currentTarget as HTMLInputElement).value) || 1) })}
669
+ />
670
+ </PropertyField>
671
+ {/if}
672
+ </PropertyGroup>
673
+
674
+ <PropertyGroup title="Transform">
675
+ <div class="mx-1 mb-1.5 flex w-full min-w-0 flex-col gap-1.5">
676
+ <div
677
+ class="flex w-full flex-nowrap items-center justify-between gap-0 overflow-x-auto rounded-xl border border-border bg-surface-elevated p-0.5 shadow-sm"
678
+ role="toolbar"
679
+ aria-label="Position"
680
+ >
681
+ {#each alignDock as action (action.id)}
682
+ {@const Icon = action.icon}
683
+ <Tooltip content={action.label} side="top" class="shrink-0">
684
+ <IconButton
685
+ label={action.label}
686
+ size="xs"
687
+ variant="ghost"
688
+ onclick={() => applyAlign(action.id)}
689
+ >
690
+ <Icon class="h-3.5 w-3.5" />
691
+ </IconButton>
692
+ </Tooltip>
693
+ {/each}
694
+ </div>
695
+ <div
696
+ class="mx-auto flex w-fit flex-nowrap items-center gap-0 rounded-xl border border-border bg-surface-elevated p-0.5 shadow-sm"
697
+ role="toolbar"
698
+ aria-label="Flip"
699
+ >
700
+ <Tooltip content="Flip horizontal" side="top" class="shrink-0">
701
+ <IconButton
702
+ label="Flip horizontal"
703
+ size="xs"
704
+ variant="ghost"
705
+ class={layer.flipX ? 'bg-brand-500/15 text-brand-600' : undefined}
706
+ aria-pressed={!!layer.flipX}
707
+ onclick={() => patch({ flipX: !layer.flipX })}
708
+ >
709
+ <FlipHorizontal2 class="h-3.5 w-3.5" />
710
+ </IconButton>
711
+ </Tooltip>
712
+ <Tooltip content="Flip vertical" side="top" class="shrink-0">
713
+ <IconButton
714
+ label="Flip vertical"
715
+ size="xs"
716
+ variant="ghost"
717
+ class={layer.flipY ? 'bg-brand-500/15 text-brand-600' : undefined}
718
+ aria-pressed={!!layer.flipY}
719
+ onclick={() => patch({ flipY: !layer.flipY })}
720
+ >
721
+ <FlipVertical2 class="h-3.5 w-3.5" />
722
+ </IconButton>
723
+ </Tooltip>
724
+ </div>
725
+ </div>
726
+
727
+ <div class="grid grid-cols-2 gap-2">
728
+ <PropertyField label="X">
729
+ <Input
730
+ type="number"
731
+ size="sm"
732
+ disabled={parentLayoutLocked}
733
+ value={String(Math.round(layer.rect.x))}
734
+ oninput={(e) =>
735
+ patchRect({ x: Number((e.currentTarget as HTMLInputElement).value) })}
736
+ />
737
+ </PropertyField>
738
+ <PropertyField label="Y">
739
+ <Input
740
+ type="number"
741
+ size="sm"
742
+ disabled={parentLayoutLocked}
743
+ value={String(Math.round(layer.rect.y))}
744
+ oninput={(e) =>
745
+ patchRect({ y: Number((e.currentTarget as HTMLInputElement).value) })}
746
+ />
747
+ </PropertyField>
748
+ <PropertyField label="W">
749
+ <Input
750
+ type="number"
751
+ size="sm"
752
+ value={String(Math.round(layer.rect.w))}
753
+ oninput={(e) =>
754
+ patchRect({ w: Number((e.currentTarget as HTMLInputElement).value) })}
755
+ />
756
+ </PropertyField>
757
+ <PropertyField label="H">
758
+ <Input
759
+ type="number"
760
+ size="sm"
761
+ value={String(Math.round(layer.rect.h))}
762
+ oninput={(e) =>
763
+ patchRect({ h: Number((e.currentTarget as HTMLInputElement).value) })}
764
+ />
765
+ </PropertyField>
766
+ </div>
767
+ {#if parentLayoutLocked}
768
+ <p class="px-1 pb-1 text-[10px] leading-snug text-muted">
769
+ X/Y los controla el layout del padre (HBox, VBox, Grid…). Usa Group / Border /
770
+ Overlay / Canvas Panel para posición libre.
771
+ </p>
772
+ {:else if layer.parentId}
773
+ <p class="px-1 pb-1 text-[10px] leading-snug text-muted">
774
+ X/Y relativos al padre (0,0 = esquina superior izquierda del contenido).
775
+ </p>
776
+ {/if}
777
+ <PropertyField
778
+ label="Rotation"
779
+ modified={fieldModified('rotation')}
780
+ onreset={() => resetField('rotation')}
781
+ >
782
+ <Slider
783
+ size="sm"
784
+ min={-180}
785
+ max={180}
786
+ step={1}
787
+ value={layer.rotation ?? 0}
788
+ showValue
789
+ valuePosition="header"
790
+ unit="°"
791
+ oninput={(v) => patch({ rotation: v })}
792
+ />
793
+ </PropertyField>
794
+ </PropertyGroup>
795
+
796
+ <PropertyGroup title="Effects">
797
+ <PropertyField
798
+ label="Shadow blur"
799
+ modified={fieldModified('shadowBlur')}
800
+ onreset={() => resetField('shadowBlur')}
801
+ >
802
+ <Slider
803
+ size="sm"
804
+ min={0}
805
+ max={64}
806
+ step={1}
807
+ value={layer.shadowBlur ?? 0}
808
+ showValue
809
+ valuePosition="header"
810
+ unit="px"
811
+ oninput={(v) => patch({ shadowBlur: v })}
812
+ />
813
+ </PropertyField>
814
+ <PropertyField
815
+ label="Shadow color"
816
+ modified={fieldModified('shadowColor')}
817
+ onreset={() => resetField('shadowColor')}
818
+ >
819
+ <ColorPicker
820
+ value={layer.shadowColor ?? '#000000'}
821
+ showSwatches={false}
822
+ onchange={(v) => patch({ shadowColor: v })}
823
+ />
824
+ </PropertyField>
825
+ <PropertyField
826
+ label="Blur"
827
+ modified={fieldModified('blur')}
828
+ onreset={() => resetField('blur')}
829
+ >
830
+ <Slider
831
+ size="sm"
832
+ min={0}
833
+ max={40}
834
+ step={1}
835
+ value={layer.blur ?? 0}
836
+ showValue
837
+ valuePosition="header"
838
+ unit="px"
839
+ oninput={(v) => patch({ blur: v })}
840
+ />
841
+ </PropertyField>
842
+ </PropertyGroup>
843
+
844
+ {#if layer.kind === 'image' || layer.kind === 'video'}
845
+ <PropertyGroup title={layer.kind === 'video' ? 'Video' : 'Image'}>
846
+ {#key layer.id}
847
+ <FileUploader
848
+ variant="single"
849
+ label=""
850
+ helperText=""
851
+ accept={layer.kind === 'video' ? 'video/*' : 'image/*'}
852
+ src={layer.src}
853
+ srcName={layer.name}
854
+ maxSizeMb={200}
855
+ onchange={replaceMedia}
856
+ onclear={() => patch({ src: undefined })}
857
+ />
858
+ {/key}
859
+ <PropertyField
860
+ label="Source"
861
+ exposed={exposedFlag('src')}
862
+ onexpose={(v) => toggleExpose('src', 'Source', v)}
863
+ >
864
+ <Input
865
+ size="sm"
866
+ value={layer.src ?? ''}
867
+ placeholder="https://…"
868
+ oninput={(e) => patch({ src: (e.currentTarget as HTMLInputElement).value || undefined })}
869
+ />
870
+ </PropertyField>
871
+ <PropertyField
872
+ label="Fit"
873
+ modified={fieldModified('objectFit')}
874
+ onreset={() => resetField('objectFit')}
875
+ >
876
+ <Select
877
+ size="sm"
878
+ options={fitOptions}
879
+ value={layer.objectFit ?? 'cover'}
880
+ onchange={(v) => patch({ objectFit: v as CanvasLayer['objectFit'] })}
881
+ />
882
+ </PropertyField>
883
+ <PropertyField
884
+ label="Corner radius"
885
+ exposed={exposedFlag('borderRadius')}
886
+ onexpose={(v) => toggleExpose('borderRadius', 'Corner radius', v)}
887
+ modified={fieldModified('borderRadius')}
888
+ onreset={() => resetField('borderRadius')}
889
+ >
890
+ <Slider
891
+ size="sm"
892
+ min={0}
893
+ max={200}
894
+ step={1}
895
+ value={layer.borderRadius ?? 0}
896
+ showValue
897
+ valuePosition="header"
898
+ unit="px"
899
+ oninput={(v) => patch({ borderRadius: v })}
900
+ />
901
+ </PropertyField>
902
+ </PropertyGroup>
903
+ {/if}
904
+
905
+ {#if layer.kind === 'text' || layer.kind === 'sticky'}
906
+ <PropertyGroup title={layer.kind === 'sticky' ? 'Sticky note' : 'Text'}>
907
+ <PropertyField
908
+ label="Content"
909
+ exposed={exposedFlag('text')}
910
+ onexpose={(v) => toggleExpose('text', 'Content', v)}
911
+ modified={fieldModified('text')}
912
+ onreset={() => resetField('text')}
913
+ >
914
+ <Textarea
915
+ rows={3}
916
+ value={layer.text ?? ''}
917
+ oninput={(e) => patch({ text: (e.currentTarget as HTMLTextAreaElement).value })}
918
+ />
919
+ </PropertyField>
920
+ <PropertyField
921
+ label="Size"
922
+ exposed={exposedFlag('fontSize')}
923
+ onexpose={(v) => toggleExpose('fontSize', 'Size', v)}
924
+ modified={fieldModified('fontSize')}
925
+ onreset={() => resetField('fontSize')}
926
+ >
927
+ <Input
928
+ type="number"
929
+ size="sm"
930
+ value={String(layer.fontSize ?? 32)}
931
+ oninput={(e) =>
932
+ patch({ fontSize: Number((e.currentTarget as HTMLInputElement).value) })}
933
+ />
934
+ </PropertyField>
935
+ <PropertyField label="Weight">
936
+ <Select
937
+ size="sm"
938
+ options={weightOptions}
939
+ value={String(layer.fontWeight ?? 600)}
940
+ onchange={(v) => patch({ fontWeight: v })}
941
+ />
942
+ </PropertyField>
943
+ <PropertyField label="Style">
944
+ <Select
945
+ size="sm"
946
+ options={styleOptions}
947
+ value={layer.fontStyle ?? 'normal'}
948
+ onchange={(v) => patch({ fontStyle: v as CanvasLayer['fontStyle'] })}
949
+ />
950
+ </PropertyField>
951
+ <PropertyField label="Decoration">
952
+ <Select
953
+ size="sm"
954
+ options={decoOptions}
955
+ value={layer.textDecoration ?? 'none'}
956
+ onchange={(v) => patch({ textDecoration: v as CanvasLayer['textDecoration'] })}
957
+ />
958
+ </PropertyField>
959
+ <PropertyField label="Align">
960
+ <Select
961
+ size="sm"
962
+ options={alignOptions}
963
+ value={layer.textAlign ?? 'left'}
964
+ onchange={(v) => patch({ textAlign: v as CanvasLayer['textAlign'] })}
965
+ />
966
+ </PropertyField>
967
+ <PropertyField
968
+ label="Color"
969
+ exposed={exposedFlag('color')}
970
+ onexpose={(v) => toggleExpose('color', 'Color', v)}
971
+ modified={fieldModified('color')}
972
+ onreset={() => resetField('color')}
973
+ >
974
+ <ColorPicker
975
+ value={layer.color ?? '#0f172a'}
976
+ onchange={(v) => patch({ color: v })}
977
+ />
978
+ </PropertyField>
979
+ {#if layer.kind === 'text'}
980
+ <PropertyField
981
+ label="Background"
982
+ exposed={exposedFlag('textBackground')}
983
+ onexpose={(v) => toggleExpose('textBackground', 'Background', v)}
984
+ modified={fieldModified('textBackground')}
985
+ onreset={() => resetField('textBackground')}
986
+ >
987
+ <ColorPicker
988
+ value={layer.textBackground ?? '#ffffff'}
989
+ alpha
990
+ onchange={(v) => patch({ textBackground: v })}
991
+ />
992
+ </PropertyField>
993
+ {/if}
994
+ {#if layer.kind === 'sticky'}
995
+ <PropertyField
996
+ label="Note color"
997
+ exposed={exposedFlag('fill')}
998
+ onexpose={(v) => toggleExpose('fill', 'Note color', v)}
999
+ modified={fieldModified('fill')}
1000
+ onreset={() => resetField('fill')}
1001
+ >
1002
+ <ColorPicker
1003
+ value={layer.fill ?? '#fef08a'}
1004
+ onchange={(v) => patch({ fill: v })}
1005
+ />
1006
+ </PropertyField>
1007
+ {/if}
1008
+ <PropertyField label="Letter spacing">
1009
+ <Input
1010
+ type="number"
1011
+ size="sm"
1012
+ value={String(layer.letterSpacing ?? 0)}
1013
+ oninput={(e) =>
1014
+ patch({ letterSpacing: Number((e.currentTarget as HTMLInputElement).value) })}
1015
+ />
1016
+ </PropertyField>
1017
+ <PropertyField label="Line height">
1018
+ <Input
1019
+ type="number"
1020
+ size="sm"
1021
+ step={0.05}
1022
+ value={String(layer.lineHeight ?? 1.15)}
1023
+ oninput={(e) =>
1024
+ patch({ lineHeight: Number((e.currentTarget as HTMLInputElement).value) })}
1025
+ />
1026
+ </PropertyField>
1027
+ </PropertyGroup>
1028
+ {/if}
1029
+
1030
+ {#if shapeKinds.includes(layer.kind) && layer.kind !== 'sticky'}
1031
+ <PropertyGroup title="Appearance">
1032
+ <PropertyField
1033
+ label="Fill"
1034
+ exposed={exposedFlag('fill')}
1035
+ onexpose={(v) => toggleExpose('fill', 'Fill', v)}
1036
+ modified={fieldModified('fill')}
1037
+ onreset={() => resetField('fill')}
1038
+ >
1039
+ <ColorPicker
1040
+ value={layer.fill ?? '#3b82f6'}
1041
+ onchange={(v) => patch({ fill: v })}
1042
+ />
1043
+ </PropertyField>
1044
+ {#if layer.kind === 'rect' || layer.kind === 'roundRect' || layer.kind === 'border'}
1045
+ <PropertyField
1046
+ label="Corner radius"
1047
+ exposed={exposedFlag('borderRadius')}
1048
+ onexpose={(v) => toggleExpose('borderRadius', 'Corner radius', v)}
1049
+ modified={fieldModified('borderRadius')}
1050
+ onreset={() => resetField('borderRadius')}
1051
+ >
1052
+ <Slider
1053
+ size="sm"
1054
+ min={0}
1055
+ max={200}
1056
+ step={1}
1057
+ value={layer.borderRadius ?? 0}
1058
+ showValue
1059
+ valuePosition="header"
1060
+ unit="px"
1061
+ oninput={(v) => patch({ borderRadius: v })}
1062
+ />
1063
+ </PropertyField>
1064
+ {/if}
1065
+ <PropertyField
1066
+ label="Stroke"
1067
+ exposed={exposedFlag('stroke')}
1068
+ onexpose={(v) => toggleExpose('stroke', 'Stroke', v)}
1069
+ modified={fieldModified('stroke')}
1070
+ onreset={() => resetField('stroke')}
1071
+ >
1072
+ <ColorPicker
1073
+ value={layer.stroke ?? '#000000'}
1074
+ onchange={(v) => patch({ stroke: v })}
1075
+ />
1076
+ </PropertyField>
1077
+ {#if layer.kind === 'line' || layer.kind === 'arrow' || layer.stroke}
1078
+ <PropertyField
1079
+ label="Stroke width"
1080
+ exposed={exposedFlag('strokeWidth')}
1081
+ onexpose={(v) => toggleExpose('strokeWidth', 'Stroke width', v)}
1082
+ >
1083
+ <Input
1084
+ type="number"
1085
+ size="sm"
1086
+ value={String(layer.strokeWidth ?? 4)}
1087
+ oninput={(e) =>
1088
+ patch({ strokeWidth: Number((e.currentTarget as HTMLInputElement).value) })}
1089
+ />
1090
+ </PropertyField>
1091
+ {/if}
1092
+ </PropertyGroup>
1093
+ {/if}
1094
+ {/if}
1095
+
1096
+ {#if doc && !layer && selectionCount <= 1}
1097
+ <PropertyGroup title={widgetDefinition ? 'Widget artboard' : 'Artboard'}>
1098
+ {#if widgetDefinition}
1099
+ <div class="grid grid-cols-2 gap-2 px-1">
1100
+ <PropertyField label="Width">
1101
+ <Input
1102
+ type="number"
1103
+ size="sm"
1104
+ value={String(doc.width)}
1105
+ oninput={(e) =>
1106
+ patchDoc({
1107
+ width: Math.max(24, Number((e.currentTarget as HTMLInputElement).value) || 24)
1108
+ })}
1109
+ />
1110
+ </PropertyField>
1111
+ <PropertyField label="Height">
1112
+ <Input
1113
+ type="number"
1114
+ size="sm"
1115
+ value={String(doc.height)}
1116
+ oninput={(e) =>
1117
+ patchDoc({
1118
+ height: Math.max(24, Number((e.currentTarget as HTMLInputElement).value) || 24)
1119
+ })}
1120
+ />
1121
+ </PropertyField>
1122
+ </div>
1123
+ {:else}
1124
+ <p class="px-1 text-[11px] text-muted">{doc.width} × {doc.height}px</p>
1125
+ {/if}
1126
+ <PropertyField label="Background">
1127
+ <ColorPicker
1128
+ value={doc.background || '#ffffff'}
1129
+ alpha
1130
+ onchange={(v) => patchDoc({ background: v })}
1131
+ />
1132
+ </PropertyField>
1133
+ {#if widgetDefinition}
1134
+ <p class="px-1 pt-1 text-[10px] text-muted">
1135
+ Select a layer to edit it. Use the eye icon on properties to expose them on instances.
1136
+ </p>
1137
+ {/if}
1138
+ </PropertyGroup>
1139
+ {/if}
1140
+ </div>