@r2digisolutions/components 0.1.6 → 0.2.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 (389) hide show
  1. package/README.md +1 -1
  2. package/dist/components/atoms/Checkbox/Checkbox.svelte +10 -3
  3. package/dist/components/atoms/Checkbox/Checkbox.svelte.d.ts +3 -0
  4. package/dist/components/atoms/IconButton/IconButton.svelte +1 -1
  5. package/dist/components/atoms/Input/Input.svelte +17 -2
  6. package/dist/components/atoms/Input/Input.svelte.d.ts +6 -1
  7. package/dist/components/atoms/MarqueeRect/MarqueeRect.svelte +21 -0
  8. package/dist/components/atoms/MarqueeRect/MarqueeRect.svelte.d.ts +8 -0
  9. package/dist/components/atoms/MediaKindIcon/MediaKindIcon.stories.js +8 -0
  10. package/dist/components/atoms/MediaKindIcon/MediaKindIcon.svelte +122 -0
  11. package/dist/components/atoms/MediaKindIcon/MediaKindIcon.svelte.d.ts +11 -0
  12. package/dist/components/atoms/MediaKindIcon/MediaKindIconStory.svelte +12 -0
  13. package/dist/components/atoms/MediaKindIcon/MediaKindIconStory.svelte.d.ts +18 -0
  14. package/dist/components/atoms/PanKnob/PanKnob.stories.d.ts +9 -0
  15. package/dist/components/atoms/PanKnob/PanKnob.stories.js +8 -0
  16. package/dist/components/atoms/PanKnob/PanKnob.svelte +218 -0
  17. package/dist/components/atoms/PanKnob/PanKnob.svelte.d.ts +19 -0
  18. package/dist/components/atoms/PanKnob/PanKnobStory.svelte +15 -0
  19. package/dist/components/atoms/PanKnob/PanKnobStory.svelte.d.ts +3 -0
  20. package/dist/components/atoms/Playhead/Playhead.stories.js +8 -0
  21. package/dist/components/atoms/Playhead/Playhead.svelte +59 -0
  22. package/dist/components/atoms/Playhead/Playhead.svelte.d.ts +13 -0
  23. package/dist/components/atoms/Playhead/PlayheadStory.svelte +9 -0
  24. package/dist/components/atoms/Playhead/PlayheadStory.svelte.d.ts +18 -0
  25. package/dist/components/atoms/Textarea/Textarea.svelte +4 -1
  26. package/dist/components/atoms/Textarea/Textarea.svelte.d.ts +1 -0
  27. package/dist/components/atoms/TimeRuler/TimeRuler.stories.js +8 -0
  28. package/dist/components/atoms/TimeRuler/TimeRuler.svelte +58 -0
  29. package/dist/components/atoms/TimeRuler/TimeRuler.svelte.d.ts +10 -0
  30. package/dist/components/atoms/TimeRuler/TimeRulerStory.svelte +7 -0
  31. package/dist/components/atoms/TimeRuler/TimeRulerStory.svelte.d.ts +18 -0
  32. package/dist/components/atoms/Toggle/Toggle.svelte +1 -1
  33. package/dist/components/atoms/Tooltip/Tooltip.svelte +1 -1
  34. package/dist/components/atoms/TrimHandle/TrimHandle.stories.js +8 -0
  35. package/dist/components/atoms/TrimHandle/TrimHandle.svelte +63 -0
  36. package/dist/components/atoms/TrimHandle/TrimHandle.svelte.d.ts +12 -0
  37. package/dist/components/atoms/TrimHandle/TrimHandleStory.svelte +11 -0
  38. package/dist/components/atoms/TrimHandle/TrimHandleStory.svelte.d.ts +18 -0
  39. package/dist/components/molecules/AiAssistPanel/AiAssistPanel.stories.d.ts +9 -0
  40. package/dist/components/molecules/AiAssistPanel/AiAssistPanel.stories.js +8 -0
  41. package/dist/components/molecules/AiAssistPanel/AiAssistPanel.svelte +102 -0
  42. package/dist/components/molecules/AiAssistPanel/AiAssistPanel.svelte.d.ts +20 -0
  43. package/dist/components/molecules/AiAssistPanel/AiAssistPanelStory.svelte +34 -0
  44. package/dist/components/molecules/AiAssistPanel/AiAssistPanelStory.svelte.d.ts +3 -0
  45. package/dist/components/molecules/BulkActionBar/BulkActionBar.svelte +112 -62
  46. package/dist/components/molecules/BulkActionBar/BulkActionBar.svelte.d.ts +2 -0
  47. package/dist/components/molecules/BulkEditPanel/BulkEditPanel.stories.js +8 -0
  48. package/dist/components/molecules/BulkEditPanel/BulkEditPanel.svelte +117 -0
  49. package/dist/components/molecules/BulkEditPanel/BulkEditPanel.svelte.d.ts +23 -0
  50. package/dist/components/molecules/BulkEditPanel/BulkEditPanelStory.svelte +18 -0
  51. package/dist/components/molecules/BulkEditPanel/BulkEditPanelStory.svelte.d.ts +18 -0
  52. package/dist/components/molecules/CanvasElementsPanel/CanvasElementsPanel.stories.js +8 -0
  53. package/dist/components/molecules/CanvasElementsPanel/CanvasElementsPanel.svelte +858 -0
  54. package/dist/components/molecules/CanvasElementsPanel/CanvasElementsPanel.svelte.d.ts +43 -0
  55. package/dist/components/molecules/CanvasElementsPanel/CanvasElementsPanelStory.svelte +7 -0
  56. package/dist/components/molecules/CanvasElementsPanel/CanvasElementsPanelStory.svelte.d.ts +18 -0
  57. package/dist/components/molecules/CanvasInspector/CanvasInspector.stories.d.ts +9 -0
  58. package/dist/components/molecules/CanvasInspector/CanvasInspector.stories.js +8 -0
  59. package/dist/components/molecules/CanvasInspector/CanvasInspector.svelte +1140 -0
  60. package/dist/components/molecules/CanvasInspector/CanvasInspector.svelte.d.ts +28 -0
  61. package/dist/components/molecules/CanvasInspector/CanvasInspectorStory.svelte +20 -0
  62. package/dist/components/molecules/CanvasInspector/CanvasInspectorStory.svelte.d.ts +3 -0
  63. package/dist/components/molecules/CodeEditor/CodeEditor.svelte +13 -10
  64. package/dist/components/molecules/ColorPicker/ColorPicker.svelte +167 -97
  65. package/dist/components/molecules/ColumnVisibilityMenu/ColumnVisibilityMenu.stories.d.ts +9 -0
  66. package/dist/components/molecules/ColumnVisibilityMenu/ColumnVisibilityMenu.stories.js +8 -0
  67. package/dist/components/molecules/ColumnVisibilityMenu/ColumnVisibilityMenu.svelte +108 -0
  68. package/dist/components/molecules/ColumnVisibilityMenu/ColumnVisibilityMenu.svelte.d.ts +18 -0
  69. package/dist/components/molecules/ColumnVisibilityMenu/ColumnVisibilityMenuStory.svelte +15 -0
  70. package/dist/components/molecules/ColumnVisibilityMenu/ColumnVisibilityMenuStory.svelte.d.ts +3 -0
  71. package/dist/components/molecules/ConditionalFormatPanel/ConditionalFormatPanel.stories.d.ts +9 -0
  72. package/dist/components/molecules/ConditionalFormatPanel/ConditionalFormatPanel.stories.js +8 -0
  73. package/dist/components/molecules/ConditionalFormatPanel/ConditionalFormatPanel.svelte +412 -0
  74. package/dist/components/molecules/ConditionalFormatPanel/ConditionalFormatPanel.svelte.d.ts +14 -0
  75. package/dist/components/molecules/ConditionalFormatPanel/ConditionalFormatPanelStory.svelte +27 -0
  76. package/dist/components/molecules/ConditionalFormatPanel/ConditionalFormatPanelStory.svelte.d.ts +3 -0
  77. package/dist/components/molecules/ConflictResolver/ConflictResolver.stories.js +8 -0
  78. package/dist/components/molecules/ConflictResolver/ConflictResolver.svelte +73 -0
  79. package/dist/components/molecules/ConflictResolver/ConflictResolver.svelte.d.ts +16 -0
  80. package/dist/components/molecules/ConflictResolver/ConflictResolverStory.svelte +11 -0
  81. package/dist/components/molecules/ConflictResolver/ConflictResolverStory.svelte.d.ts +18 -0
  82. package/dist/components/molecules/ContextMenu/ContextMenu.svelte +237 -41
  83. package/dist/components/molecules/ContextMenu/ContextMenu.svelte.d.ts +17 -1
  84. package/dist/components/molecules/DateTimePicker/DateTimePicker.svelte.d.ts +1 -1
  85. package/dist/components/molecules/ExpressionEditor/ExpressionEditor.stories.d.ts +9 -0
  86. package/dist/components/molecules/ExpressionEditor/ExpressionEditor.stories.js +8 -0
  87. package/dist/components/molecules/ExpressionEditor/ExpressionEditor.svelte +56 -0
  88. package/dist/components/molecules/ExpressionEditor/ExpressionEditor.svelte.d.ts +12 -0
  89. package/dist/components/molecules/ExpressionEditor/ExpressionEditorStory.svelte +12 -0
  90. package/dist/components/molecules/ExpressionEditor/ExpressionEditorStory.svelte.d.ts +3 -0
  91. package/dist/components/molecules/FilterList/FilterList.stories.d.ts +9 -0
  92. package/dist/components/molecules/FilterList/FilterList.stories.js +8 -0
  93. package/dist/components/molecules/FilterList/FilterList.svelte +101 -0
  94. package/dist/components/molecules/FilterList/FilterList.svelte.d.ts +18 -0
  95. package/dist/components/molecules/FilterList/FilterListStory.svelte +31 -0
  96. package/dist/components/molecules/FilterList/FilterListStory.svelte.d.ts +3 -0
  97. package/dist/components/molecules/FormDateTimePicker/FormDateTimePicker.svelte.d.ts +1 -1
  98. package/dist/components/molecules/Gauge/Gauge.stories.d.ts +1 -1
  99. package/dist/components/molecules/InfiniteScroll/InfiniteScroll.stories.d.ts +1 -1
  100. package/dist/components/molecules/MediaAssetBrowser/MediaAssetBrowser.stories.d.ts +9 -0
  101. package/dist/components/molecules/MediaAssetBrowser/MediaAssetBrowser.stories.js +8 -0
  102. package/dist/components/molecules/MediaAssetBrowser/MediaAssetBrowser.svelte +94 -0
  103. package/dist/components/molecules/MediaAssetBrowser/MediaAssetBrowser.svelte.d.ts +15 -0
  104. package/dist/components/molecules/MediaAssetBrowser/MediaAssetBrowserStory.svelte +18 -0
  105. package/dist/components/molecules/MediaAssetBrowser/MediaAssetBrowserStory.svelte.d.ts +3 -0
  106. package/dist/components/molecules/MediaAssetCard/MediaAssetCard.stories.js +8 -0
  107. package/dist/components/molecules/MediaAssetCard/MediaAssetCard.svelte +50 -0
  108. package/dist/components/molecules/MediaAssetCard/MediaAssetCard.svelte.d.ts +11 -0
  109. package/dist/components/molecules/MediaAssetCard/MediaAssetCardStory.svelte +13 -0
  110. package/dist/components/molecules/MediaAssetCard/MediaAssetCardStory.svelte.d.ts +18 -0
  111. package/dist/components/molecules/MediaLayerItem/MediaLayerItem.stories.js +8 -0
  112. package/dist/components/molecules/MediaLayerItem/MediaLayerItem.svelte +380 -0
  113. package/dist/components/molecules/MediaLayerItem/MediaLayerItem.svelte.d.ts +33 -0
  114. package/dist/components/molecules/MediaLayerItem/MediaLayerItemStory.svelte +14 -0
  115. package/dist/components/molecules/MediaLayerItem/MediaLayerItemStory.svelte.d.ts +18 -0
  116. package/dist/components/molecules/MediaLayerList/MediaLayerList.stories.d.ts +9 -0
  117. package/dist/components/molecules/MediaLayerList/MediaLayerList.stories.js +8 -0
  118. package/dist/components/molecules/MediaLayerList/MediaLayerList.svelte +399 -0
  119. package/dist/components/molecules/MediaLayerList/MediaLayerList.svelte.d.ts +37 -0
  120. package/dist/components/molecules/MediaLayerList/MediaLayerListStory.svelte +24 -0
  121. package/dist/components/molecules/MediaLayerList/MediaLayerListStory.svelte.d.ts +3 -0
  122. package/dist/components/molecules/MediaStage/MediaStage.stories.d.ts +9 -0
  123. package/dist/components/molecules/MediaStage/MediaStage.stories.js +8 -0
  124. package/dist/components/molecules/MediaStage/MediaStage.svelte +1498 -0
  125. package/dist/components/molecules/MediaStage/MediaStage.svelte.d.ts +45 -0
  126. package/dist/components/molecules/MediaStage/MediaStageStory.svelte +35 -0
  127. package/dist/components/molecules/MediaStage/MediaStageStory.svelte.d.ts +3 -0
  128. package/dist/components/molecules/MediaTimeline/MediaTimeline.stories.d.ts +9 -0
  129. package/dist/components/molecules/MediaTimeline/MediaTimeline.stories.js +8 -0
  130. package/dist/components/molecules/MediaTimeline/MediaTimeline.svelte +131 -0
  131. package/dist/components/molecules/MediaTimeline/MediaTimeline.svelte.d.ts +19 -0
  132. package/dist/components/molecules/MediaTimeline/MediaTimelineStory.svelte +20 -0
  133. package/dist/components/molecules/MediaTimeline/MediaTimelineStory.svelte.d.ts +3 -0
  134. package/dist/components/molecules/MixerChannel/MixerChannel.stories.d.ts +9 -0
  135. package/dist/components/molecules/MixerChannel/MixerChannel.stories.js +8 -0
  136. package/dist/components/molecules/MixerChannel/MixerChannel.svelte +92 -0
  137. package/dist/components/molecules/MixerChannel/MixerChannel.svelte.d.ts +11 -0
  138. package/dist/components/molecules/MixerChannel/MixerChannelStory.svelte +13 -0
  139. package/dist/components/molecules/MixerChannel/MixerChannelStory.svelte.d.ts +3 -0
  140. package/dist/components/molecules/NodeGraph/GraphBlueprintNode.svelte +454 -0
  141. package/dist/components/molecules/NodeGraph/GraphBlueprintNode.svelte.d.ts +8 -0
  142. package/dist/components/molecules/NodeGraph/GraphFlowBridge.svelte +26 -0
  143. package/dist/components/molecules/NodeGraph/GraphFlowBridge.svelte.d.ts +22 -0
  144. package/dist/components/molecules/NodeGraph/NodeGraph.stories.d.ts +12 -0
  145. package/dist/components/molecules/NodeGraph/NodeGraph.stories.js +9 -0
  146. package/dist/components/molecules/NodeGraph/NodeGraph.svelte +1409 -0
  147. package/dist/components/molecules/NodeGraph/NodeGraph.svelte.d.ts +33 -0
  148. package/dist/components/molecules/NodeGraph/NodeGraphStory.svelte +90 -0
  149. package/dist/components/molecules/NodeGraph/NodeGraphStory.svelte.d.ts +3 -0
  150. package/dist/components/molecules/NodePalette/NodePalette.stories.js +8 -0
  151. package/dist/components/molecules/NodePalette/NodePalette.svelte +86 -0
  152. package/dist/components/molecules/NodePalette/NodePalette.svelte.d.ts +11 -0
  153. package/dist/components/molecules/NodePalette/NodePaletteStory.svelte +11 -0
  154. package/dist/components/molecules/NodePalette/NodePaletteStory.svelte.d.ts +18 -0
  155. package/dist/components/molecules/Poll/Poll.stories.d.ts +1 -1
  156. package/dist/components/molecules/ProgramMonitor/ProgramMonitor.stories.js +8 -0
  157. package/dist/components/molecules/ProgramMonitor/ProgramMonitor.svelte +72 -0
  158. package/dist/components/molecules/ProgramMonitor/ProgramMonitor.svelte.d.ts +12 -0
  159. package/dist/components/molecules/ProgramMonitor/ProgramMonitorStory.svelte +16 -0
  160. package/dist/components/molecules/ProgramMonitor/ProgramMonitorStory.svelte.d.ts +18 -0
  161. package/dist/components/molecules/PropertyField/PropertyField.svelte +57 -3
  162. package/dist/components/molecules/PropertyField/PropertyField.svelte.d.ts +10 -0
  163. package/dist/components/molecules/PropertyField/PropertyFieldStory.svelte +21 -0
  164. package/dist/components/molecules/PropertyGroup/PropertyGroup.svelte +1 -1
  165. package/dist/components/molecules/QueryBuilder/QueryBuilder.stories.d.ts +9 -0
  166. package/dist/components/molecules/QueryBuilder/QueryBuilder.stories.js +8 -0
  167. package/dist/components/molecules/QueryBuilder/QueryBuilder.svelte +52 -0
  168. package/dist/components/molecules/QueryBuilder/QueryBuilder.svelte.d.ts +18 -0
  169. package/dist/components/molecules/QueryBuilder/QueryBuilderStory.svelte +62 -0
  170. package/dist/components/molecules/QueryBuilder/QueryBuilderStory.svelte.d.ts +3 -0
  171. package/dist/components/molecules/RelationPicker/RelationPicker.stories.d.ts +9 -0
  172. package/dist/components/molecules/RelationPicker/RelationPicker.stories.js +8 -0
  173. package/dist/components/molecules/RelationPicker/RelationPicker.svelte +180 -0
  174. package/dist/components/molecules/RelationPicker/RelationPicker.svelte.d.ts +24 -0
  175. package/dist/components/molecules/RelationPicker/RelationPickerStory.svelte +16 -0
  176. package/dist/components/molecules/RelationPicker/RelationPickerStory.svelte.d.ts +3 -0
  177. package/dist/components/molecules/SchemaFieldBuilder/SchemaFieldBuilder.stories.d.ts +9 -0
  178. package/dist/components/molecules/SchemaFieldBuilder/SchemaFieldBuilder.stories.js +8 -0
  179. package/dist/components/molecules/SchemaFieldBuilder/SchemaFieldBuilder.svelte +154 -0
  180. package/dist/components/molecules/SchemaFieldBuilder/SchemaFieldBuilder.svelte.d.ts +12 -0
  181. package/dist/components/molecules/SchemaFieldBuilder/SchemaFieldBuilderStory.svelte +16 -0
  182. package/dist/components/molecules/SchemaFieldBuilder/SchemaFieldBuilderStory.svelte.d.ts +3 -0
  183. package/dist/components/molecules/SecretField/SecretField.stories.d.ts +9 -0
  184. package/dist/components/molecules/SecretField/SecretField.stories.js +8 -0
  185. package/dist/components/molecules/SecretField/SecretField.svelte +58 -0
  186. package/dist/components/molecules/SecretField/SecretField.svelte.d.ts +15 -0
  187. package/dist/components/molecules/SecretField/SecretFieldStory.svelte +8 -0
  188. package/dist/components/molecules/SecretField/SecretFieldStory.svelte.d.ts +3 -0
  189. package/dist/components/molecules/SplitPane/SplitPane.svelte +96 -37
  190. package/dist/components/molecules/SplitPane/SplitPane.svelte.d.ts +10 -2
  191. package/dist/components/molecules/TableToolbar/TableToolbar.svelte.d.ts +1 -1
  192. package/dist/components/molecules/Terminal/Terminal.stories.js +20 -0
  193. package/dist/components/molecules/Terminal/Terminal.svelte +238 -0
  194. package/dist/components/molecules/Terminal/Terminal.svelte.d.ts +19 -0
  195. package/dist/components/molecules/Terminal/TerminalStory.svelte +47 -0
  196. package/dist/components/molecules/Terminal/TerminalStory.svelte.d.ts +6 -0
  197. package/dist/components/molecules/TimelineClip/TimelineClip.stories.js +8 -0
  198. package/dist/components/molecules/TimelineClip/TimelineClip.svelte +116 -0
  199. package/dist/components/molecules/TimelineClip/TimelineClip.svelte.d.ts +15 -0
  200. package/dist/components/molecules/TimelineClip/TimelineClipStory.svelte +18 -0
  201. package/dist/components/molecules/TimelineClip/TimelineClipStory.svelte.d.ts +18 -0
  202. package/dist/components/molecules/TimelineTrack/TimelineTrack.stories.js +8 -0
  203. package/dist/components/molecules/TimelineTrack/TimelineTrack.svelte +56 -0
  204. package/dist/components/molecules/TimelineTrack/TimelineTrack.svelte.d.ts +16 -0
  205. package/dist/components/molecules/TimelineTrack/TimelineTrackStory.svelte +35 -0
  206. package/dist/components/molecules/TimelineTrack/TimelineTrackStory.svelte.d.ts +18 -0
  207. package/dist/components/molecules/TraceWaterfall/TraceWaterfall.stories.js +8 -0
  208. package/dist/components/molecules/TraceWaterfall/TraceWaterfall.svelte +158 -0
  209. package/dist/components/molecules/TraceWaterfall/TraceWaterfall.svelte.d.ts +18 -0
  210. package/dist/components/molecules/TraceWaterfall/TraceWaterfallStory.svelte +55 -0
  211. package/dist/components/molecules/TraceWaterfall/TraceWaterfallStory.svelte.d.ts +18 -0
  212. package/dist/components/molecules/TrackHeader/TrackHeader.stories.d.ts +9 -0
  213. package/dist/components/molecules/TrackHeader/TrackHeader.stories.js +8 -0
  214. package/dist/components/molecules/TrackHeader/TrackHeader.svelte +54 -0
  215. package/dist/components/molecules/TrackHeader/TrackHeader.svelte.d.ts +9 -0
  216. package/dist/components/molecules/TrackHeader/TrackHeaderStory.svelte +10 -0
  217. package/dist/components/molecules/TrackHeader/TrackHeaderStory.svelte.d.ts +3 -0
  218. package/dist/components/molecules/TransportControls/TransportControls.stories.d.ts +9 -0
  219. package/dist/components/molecules/TransportControls/TransportControls.stories.js +8 -0
  220. package/dist/components/molecules/TransportControls/TransportControls.svelte +53 -0
  221. package/dist/components/molecules/TransportControls/TransportControls.svelte.d.ts +12 -0
  222. package/dist/components/molecules/TransportControls/TransportControlsStory.svelte +18 -0
  223. package/dist/components/molecules/TransportControls/TransportControlsStory.svelte.d.ts +3 -0
  224. package/dist/components/molecules/VersionHistoryPanel/VersionHistoryPanel.stories.js +8 -0
  225. package/dist/components/molecules/VersionHistoryPanel/VersionHistoryPanel.svelte +117 -0
  226. package/dist/components/molecules/VersionHistoryPanel/VersionHistoryPanel.svelte.d.ts +20 -0
  227. package/dist/components/molecules/VersionHistoryPanel/VersionHistoryPanelStory.svelte +36 -0
  228. package/dist/components/molecules/VersionHistoryPanel/VersionHistoryPanelStory.svelte.d.ts +18 -0
  229. package/dist/components/molecules/VideoPlayer/VideoPlayer.stories.d.ts +1 -1
  230. package/dist/components/molecules/VideoTrackHeader/VideoTrackHeader.stories.d.ts +9 -0
  231. package/dist/components/molecules/VideoTrackHeader/VideoTrackHeader.stories.js +8 -0
  232. package/dist/components/molecules/VideoTrackHeader/VideoTrackHeader.svelte +59 -0
  233. package/dist/components/molecules/VideoTrackHeader/VideoTrackHeader.svelte.d.ts +9 -0
  234. package/dist/components/molecules/VideoTrackHeader/VideoTrackHeaderStory.svelte +10 -0
  235. package/dist/components/molecules/VideoTrackHeader/VideoTrackHeaderStory.svelte.d.ts +3 -0
  236. package/dist/components/molecules/WaveformRegion/WaveformRegion.stories.js +8 -0
  237. package/dist/components/molecules/WaveformRegion/WaveformRegion.svelte +82 -0
  238. package/dist/components/molecules/WaveformRegion/WaveformRegion.svelte.d.ts +13 -0
  239. package/dist/components/molecules/WaveformRegion/WaveformRegionStory.svelte +17 -0
  240. package/dist/components/molecules/WaveformRegion/WaveformRegionStory.svelte.d.ts +18 -0
  241. package/dist/components/molecules/WidgetCanvas/WidgetCanvas.svelte +13 -4
  242. package/dist/components/molecules/WidgetCanvas/WidgetCanvas.svelte.d.ts +3 -1
  243. package/dist/components/molecules/WidgetCanvas/widgetCanvasContext.d.ts +2 -0
  244. package/dist/components/molecules/WidgetFrame/WidgetFrame.svelte +206 -37
  245. package/dist/components/molecules/WidgetFrame/WidgetFrame.svelte.d.ts +31 -0
  246. package/dist/components/organisms/AssetPickerPage/AssetPickerPage.svelte.d.ts +1 -1
  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 +273 -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/BacklogPage/BacklogPage.svelte.d.ts +1 -1
  254. package/dist/components/organisms/BlogEditor/BlogEditor.stories.d.ts +12 -0
  255. package/dist/components/organisms/BlogEditor/BlogEditor.stories.js +9 -0
  256. package/dist/components/organisms/BlogEditor/BlogEditor.svelte +1208 -0
  257. package/dist/components/organisms/BlogEditor/BlogEditor.svelte.d.ts +16 -0
  258. package/dist/components/organisms/BlogEditor/BlogEditorStory.svelte +144 -0
  259. package/dist/components/organisms/BlogEditor/BlogEditorStory.svelte.d.ts +3 -0
  260. package/dist/components/organisms/BlogEditor/DemoBlogCard.svelte +28 -0
  261. package/dist/components/organisms/BlogEditor/DemoBlogCard.svelte.d.ts +10 -0
  262. package/dist/components/organisms/BlogEditor/DemoBlogStats.svelte +34 -0
  263. package/dist/components/organisms/BlogEditor/DemoBlogStats.svelte.d.ts +11 -0
  264. package/dist/components/organisms/BlogEditor/DemoBlogWidget.svelte +13 -0
  265. package/dist/components/organisms/BlogEditor/DemoBlogWidget.svelte.d.ts +8 -0
  266. package/dist/components/organisms/BlogRenderer/BlogRenderer.stories.js +8 -0
  267. package/dist/components/organisms/BlogRenderer/BlogRenderer.svelte +469 -0
  268. package/dist/components/organisms/BlogRenderer/BlogRenderer.svelte.d.ts +14 -0
  269. package/dist/components/organisms/BlogRenderer/BlogRendererStory.svelte +20 -0
  270. package/dist/components/organisms/BlogRenderer/BlogRendererStory.svelte.d.ts +18 -0
  271. package/dist/components/organisms/BlueprintEditor/BlueprintEditor.stories.d.ts +12 -0
  272. package/dist/components/organisms/BlueprintEditor/BlueprintEditor.stories.js +9 -0
  273. package/dist/components/organisms/BlueprintEditor/BlueprintEditor.svelte +1012 -0
  274. package/dist/components/organisms/BlueprintEditor/BlueprintEditor.svelte.d.ts +16 -0
  275. package/dist/components/organisms/BlueprintEditor/BlueprintEditorStory.svelte +76 -0
  276. package/dist/components/organisms/BlueprintEditor/BlueprintEditorStory.svelte.d.ts +3 -0
  277. package/dist/components/organisms/CalendarApp/CalendarApp.svelte.d.ts +1 -1
  278. package/dist/components/organisms/CanvasEditor/CanvasEditor.stories.d.ts +12 -0
  279. package/dist/components/organisms/CanvasEditor/CanvasEditor.stories.js +9 -0
  280. package/dist/components/organisms/CanvasEditor/CanvasEditor.svelte +1680 -0
  281. package/dist/components/organisms/CanvasEditor/CanvasEditor.svelte.d.ts +18 -0
  282. package/dist/components/organisms/CanvasEditor/CanvasEditorStory.svelte +329 -0
  283. package/dist/components/organisms/CanvasEditor/CanvasEditorStory.svelte.d.ts +3 -0
  284. package/dist/components/organisms/DashboardBuilderPage/DashboardBuilderPage.svelte.d.ts +1 -1
  285. package/dist/components/organisms/DataGrid/DataGrid.stories.d.ts +65 -0
  286. package/dist/components/organisms/DataGrid/DataGrid.stories.js +95 -0
  287. package/dist/components/organisms/DataGrid/DataGrid.svelte +2264 -0
  288. package/dist/components/organisms/DataGrid/DataGrid.svelte.d.ts +99 -0
  289. package/dist/components/organisms/DataGrid/DataGridStory.svelte +659 -0
  290. package/dist/components/organisms/DataGrid/DataGridStory.svelte.d.ts +11 -0
  291. package/dist/components/organisms/DataGrid/breakpoints.d.ts +10 -0
  292. package/dist/components/organisms/DataGrid/breakpoints.js +20 -0
  293. package/dist/components/organisms/DataGrid/cellEditors.d.ts +8 -0
  294. package/dist/components/organisms/DataGrid/cellEditors.js +59 -0
  295. package/dist/components/organisms/DataGrid/conditionalFormat.d.ts +11 -0
  296. package/dist/components/organisms/DataGrid/conditionalFormat.js +98 -0
  297. package/dist/components/organisms/DataGrid/filterRows.d.ts +5 -0
  298. package/dist/components/organisms/DataGrid/filterRows.js +60 -0
  299. package/dist/components/organisms/DataGrid/marks.d.ts +9 -0
  300. package/dist/components/organisms/DataGrid/marks.js +91 -0
  301. package/dist/components/organisms/DataGrid/types.d.ts +126 -0
  302. package/dist/components/organisms/DataGrid/types.js +21 -0
  303. package/dist/components/organisms/DesktopShell/DesktopShell.svelte.d.ts +1 -1
  304. package/dist/components/organisms/EditorShell/EditorShell.svelte +123 -28
  305. package/dist/components/organisms/EditorShell/EditorShell.svelte.d.ts +21 -1
  306. package/dist/components/organisms/FileUploader/FileUploader.svelte +77 -15
  307. package/dist/components/organisms/FileUploader/FileUploader.svelte.d.ts +11 -0
  308. package/dist/components/organisms/ImportWizard/ImportWizard.stories.js +8 -0
  309. package/dist/components/organisms/ImportWizard/ImportWizard.svelte +209 -0
  310. package/dist/components/organisms/ImportWizard/ImportWizard.svelte.d.ts +22 -0
  311. package/dist/components/organisms/ImportWizard/ImportWizardStory.svelte +16 -0
  312. package/dist/components/organisms/ImportWizard/ImportWizardStory.svelte.d.ts +18 -0
  313. package/dist/components/organisms/ResourceStudio/ResourceStudio.stories.d.ts +33 -0
  314. package/dist/components/organisms/ResourceStudio/ResourceStudio.stories.js +56 -0
  315. package/dist/components/organisms/ResourceStudio/ResourceStudio.svelte +830 -0
  316. package/dist/components/organisms/ResourceStudio/ResourceStudio.svelte.d.ts +68 -0
  317. package/dist/components/organisms/ResourceStudio/ResourceStudioStory.svelte +600 -0
  318. package/dist/components/organisms/ResourceStudio/ResourceStudioStory.svelte.d.ts +7 -0
  319. package/dist/components/organisms/ResourceStudio/fieldsToColumns.d.ts +4 -0
  320. package/dist/components/organisms/ResourceStudio/fieldsToColumns.js +20 -0
  321. package/dist/components/organisms/ResourceStudio/fieldsToSchema.d.ts +6 -0
  322. package/dist/components/organisms/ResourceStudio/fieldsToSchema.js +53 -0
  323. package/dist/components/organisms/ResourceStudio/types.d.ts +69 -0
  324. package/dist/components/organisms/ResourceStudio/types.js +15 -0
  325. package/dist/components/organisms/Scheduler/Scheduler.svelte.d.ts +1 -1
  326. package/dist/components/organisms/SchemaForm/SchemaForm.svelte +10 -3
  327. package/dist/components/organisms/SchemaForm/SchemaForm.svelte.d.ts +1 -0
  328. package/dist/components/organisms/VideoEditor/VideoEditor.stories.d.ts +12 -0
  329. package/dist/components/organisms/VideoEditor/VideoEditor.stories.js +9 -0
  330. package/dist/components/organisms/VideoEditor/VideoEditor.svelte +308 -0
  331. package/dist/components/organisms/VideoEditor/VideoEditor.svelte.d.ts +13 -0
  332. package/dist/components/organisms/VideoEditor/VideoEditorStory.svelte +10 -0
  333. package/dist/components/organisms/VideoEditor/VideoEditorStory.svelte.d.ts +3 -0
  334. package/dist/components/templates/AudioEditorTemplate/AudioEditorTemplate.stories.d.ts +12 -0
  335. package/dist/components/templates/AudioEditorTemplate/AudioEditorTemplate.stories.js +9 -0
  336. package/dist/components/templates/AudioEditorTemplate/AudioEditorTemplate.svelte +22 -0
  337. package/dist/components/templates/AudioEditorTemplate/AudioEditorTemplate.svelte.d.ts +13 -0
  338. package/dist/components/templates/AudioEditorTemplate/AudioEditorTemplateStory.svelte +8 -0
  339. package/dist/components/templates/AudioEditorTemplate/AudioEditorTemplateStory.svelte.d.ts +3 -0
  340. package/dist/components/templates/CanvasEditorTemplate/CanvasEditorTemplate.stories.d.ts +12 -0
  341. package/dist/components/templates/CanvasEditorTemplate/CanvasEditorTemplate.stories.js +9 -0
  342. package/dist/components/templates/CanvasEditorTemplate/CanvasEditorTemplate.svelte +32 -0
  343. package/dist/components/templates/CanvasEditorTemplate/CanvasEditorTemplate.svelte.d.ts +17 -0
  344. package/dist/components/templates/CanvasEditorTemplate/CanvasEditorTemplateStory.svelte +21 -0
  345. package/dist/components/templates/CanvasEditorTemplate/CanvasEditorTemplateStory.svelte.d.ts +3 -0
  346. package/dist/components/templates/ResourceStudioTemplate/ResourceStudioTemplate.stories.d.ts +25 -0
  347. package/dist/components/templates/ResourceStudioTemplate/ResourceStudioTemplate.stories.js +18 -0
  348. package/dist/components/templates/ResourceStudioTemplate/ResourceStudioTemplate.svelte +192 -0
  349. package/dist/components/templates/ResourceStudioTemplate/ResourceStudioTemplate.svelte.d.ts +62 -0
  350. package/dist/components/templates/ResourceStudioTemplate/ResourceStudioTemplateStory.svelte +129 -0
  351. package/dist/components/templates/ResourceStudioTemplate/ResourceStudioTemplateStory.svelte.d.ts +7 -0
  352. package/dist/components/templates/VideoEditorTemplate/VideoEditorTemplate.stories.d.ts +12 -0
  353. package/dist/components/templates/VideoEditorTemplate/VideoEditorTemplate.stories.js +9 -0
  354. package/dist/components/templates/VideoEditorTemplate/VideoEditorTemplate.svelte +22 -0
  355. package/dist/components/templates/VideoEditorTemplate/VideoEditorTemplate.svelte.d.ts +13 -0
  356. package/dist/components/templates/VideoEditorTemplate/VideoEditorTemplateStory.svelte +8 -0
  357. package/dist/components/templates/VideoEditorTemplate/VideoEditorTemplateStory.svelte.d.ts +3 -0
  358. package/dist/index.d.ts +94 -1
  359. package/dist/index.js +68 -0
  360. package/dist/types/xyflow-svelte.d.ts +62 -0
  361. package/dist/utils/audioProject.d.ts +19 -0
  362. package/dist/utils/audioProject.js +70 -0
  363. package/dist/utils/blogDocument.d.ts +175 -0
  364. package/dist/utils/blogDocument.js +220 -0
  365. package/dist/utils/blueprintRuntime.d.ts +34 -0
  366. package/dist/utils/blueprintRuntime.js +289 -0
  367. package/dist/utils/canvasDocument.d.ts +239 -0
  368. package/dist/utils/canvasDocument.js +443 -0
  369. package/dist/utils/canvasExport.d.ts +10 -0
  370. package/dist/utils/canvasExport.js +469 -0
  371. package/dist/utils/canvasHierarchy.d.ts +189 -0
  372. package/dist/utils/canvasHierarchy.js +674 -0
  373. package/dist/utils/canvasHistory.d.ts +19 -0
  374. package/dist/utils/canvasHistory.js +48 -0
  375. package/dist/utils/canvasWidget.d.ts +81 -0
  376. package/dist/utils/canvasWidget.js +597 -0
  377. package/dist/utils/marqueeSelect.d.ts +48 -0
  378. package/dist/utils/marqueeSelect.js +189 -0
  379. package/dist/utils/mediaTime.d.ts +16 -0
  380. package/dist/utils/mediaTime.js +57 -0
  381. package/dist/utils/mediaTracks.d.ts +61 -0
  382. package/dist/utils/mediaTracks.js +102 -0
  383. package/dist/utils/nodeGraph.d.ts +354 -0
  384. package/dist/utils/nodeGraph.js +1453 -0
  385. package/dist/utils/queryBridge.d.ts +18 -0
  386. package/dist/utils/queryBridge.js +118 -0
  387. package/dist/utils/videoSequence.d.ts +13 -0
  388. package/dist/utils/videoSequence.js +63 -0
  389. 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>