@keyfunc/keybricks-ds 1.0.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 (418) hide show
  1. package/DEPLOY.md +204 -0
  2. package/DESIGN.md +269 -0
  3. package/INTEGRATION.md +417 -0
  4. package/SKILL.md +32 -0
  5. package/_adherence.oxlintrc.json +1469 -0
  6. package/_scripts/build-index.mjs +80 -0
  7. package/_scripts/build-tokens.mjs +135 -0
  8. package/assets/icons/icon-index.js +1 -0
  9. package/assets/icons/icon-index.json +1 -0
  10. package/assets/icons/unicons-index.js +1 -0
  11. package/assets/icons/unicons-index.json +1 -0
  12. package/assets/keybricks-logo.png +0 -0
  13. package/components/_cards/accordion.card.html +32 -0
  14. package/components/_cards/action-chip.card.html +22 -0
  15. package/components/_cards/activity.card.html +34 -0
  16. package/components/_cards/alert.card.html +32 -0
  17. package/components/_cards/app-chrome.card.html +36 -0
  18. package/components/_cards/banner.card.html +21 -0
  19. package/components/_cards/brand-visual.card.html +43 -0
  20. package/components/_cards/breadcrumb.card.html +23 -0
  21. package/components/_cards/button-1-base.card.html +39 -0
  22. package/components/_cards/button-2-states.card.html +56 -0
  23. package/components/_cards/button-3-sizes-icons.card.html +32 -0
  24. package/components/_cards/button-4-group.card.html +47 -0
  25. package/components/_cards/canvas-zoom-controls.card.html +19 -0
  26. package/components/_cards/cards-indicators.card.html +59 -0
  27. package/components/_cards/charts-1-sparkline.card.html +55 -0
  28. package/components/_cards/charts-10-gauge.card.html +31 -0
  29. package/components/_cards/charts-11-funnel.card.html +28 -0
  30. package/components/_cards/charts-12-treemap.card.html +23 -0
  31. package/components/_cards/charts-14-radar.card.html +31 -0
  32. package/components/_cards/charts-15-distribution.card.html +32 -0
  33. package/components/_cards/charts-16-pareto.card.html +25 -0
  34. package/components/_cards/charts-17-candlestick.card.html +34 -0
  35. package/components/_cards/charts-18-sankey.card.html +29 -0
  36. package/components/_cards/charts-19-chord.card.html +31 -0
  37. package/components/_cards/charts-2-line.card.html +46 -0
  38. package/components/_cards/charts-20-sunburst.card.html +38 -0
  39. package/components/_cards/charts-21-worldmap.card.html +33 -0
  40. package/components/_cards/charts-22-gantt.card.html +37 -0
  41. package/components/_cards/charts-23-bar3d.card.html +26 -0
  42. package/components/_cards/charts-24-pie3d.card.html +32 -0
  43. package/components/_cards/charts-25-surface3d.card.html +24 -0
  44. package/components/_cards/charts-26-scatter3d.card.html +24 -0
  45. package/components/_cards/charts-27-ribbon3d.card.html +23 -0
  46. package/components/_cards/charts-3-bar.card.html +71 -0
  47. package/components/_cards/charts-4-barlist.card.html +30 -0
  48. package/components/_cards/charts-5-donut.card.html +35 -0
  49. package/components/_cards/charts-6-scatter.card.html +26 -0
  50. package/components/_cards/charts-7-heatmap.card.html +28 -0
  51. package/components/_cards/charts-8-waterfall.card.html +25 -0
  52. package/components/_cards/charts-9-bullet.card.html +31 -0
  53. package/components/_cards/charts-99-fullpage.card.html +194 -0
  54. package/components/_cards/checkbox.card.html +34 -0
  55. package/components/_cards/codeblock.card.html +19 -0
  56. package/components/_cards/combobox.card.html +25 -0
  57. package/components/_cards/context-menu.card.html +21 -0
  58. package/components/_cards/datatable.card.html +48 -0
  59. package/components/_cards/date-picker.card.html +31 -0
  60. package/components/_cards/diffvalue.card.html +21 -0
  61. package/components/_cards/divider.card.html +24 -0
  62. package/components/_cards/drawer.card.html +30 -0
  63. package/components/_cards/dropdown-menu.card.html +38 -0
  64. package/components/_cards/dropzone.card.html +22 -0
  65. package/components/_cards/empty-state.card.html +29 -0
  66. package/components/_cards/filter-bar.card.html +34 -0
  67. package/components/_cards/icon-button.card.html +27 -0
  68. package/components/_cards/icons-1-core.card.html +49 -0
  69. package/components/_cards/icons-2-feather.card.html +39 -0
  70. package/components/_cards/icons-3-unicons.card.html +44 -0
  71. package/components/_cards/input.card.html +25 -0
  72. package/components/_cards/kbd.card.html +20 -0
  73. package/components/_cards/keyvalue.card.html +23 -0
  74. package/components/_cards/listrow.card.html +30 -0
  75. package/components/_cards/loading.card.html +33 -0
  76. package/components/_cards/log-viewer.card.html +23 -0
  77. package/components/_cards/modal.card.html +35 -0
  78. package/components/_cards/multi-select.card.html +26 -0
  79. package/components/_cards/number-stepper.card.html +24 -0
  80. package/components/_cards/pagination.card.html +25 -0
  81. package/components/_cards/people.card.html +46 -0
  82. package/components/_cards/pipeline-node.card.html +76 -0
  83. package/components/_cards/pipeline-palette.card.html +54 -0
  84. package/components/_cards/search.card.html +23 -0
  85. package/components/_cards/select.card.html +23 -0
  86. package/components/_cards/slider.card.html +25 -0
  87. package/components/_cards/smart-table.card.html +37 -0
  88. package/components/_cards/spreadsheet.card.html +31 -0
  89. package/components/_cards/stepper.card.html +25 -0
  90. package/components/_cards/tabs.card.html +25 -0
  91. package/components/_cards/tag.card.html +26 -0
  92. package/components/_cards/textarea.card.html +27 -0
  93. package/components/_cards/timeline.card.html +32 -0
  94. package/components/_cards/toast.card.html +33 -0
  95. package/components/_cards/toggles.card.html +68 -0
  96. package/components/_cards/tooltip.card.html +22 -0
  97. package/components/_cards/tree.card.html +150 -0
  98. package/components/_shared/frame-theme.js +16 -0
  99. package/components/_shared/src-brand.js +1 -0
  100. package/components/_shared/src-buttons.js +1 -0
  101. package/components/_shared/src-charts.js +1 -0
  102. package/components/_shared/src-data.js +1 -0
  103. package/components/_shared/src-display.js +1 -0
  104. package/components/_shared/src-feedback.js +1 -0
  105. package/components/_shared/src-forms.js +1 -0
  106. package/components/_shared/src-icons.js +1 -0
  107. package/components/_shared/src-navigation.js +1 -0
  108. package/components/_shared/src-pipeline.js +1 -0
  109. package/components/_shared/src-tabs.js +1 -0
  110. package/components/_shared/svg-download.js +19 -0
  111. package/components/_shared/view-source.js +185 -0
  112. package/components/_vue/index.mjs +114 -0
  113. package/components/brand/BrandVisual.d.ts +17 -0
  114. package/components/brand/BrandVisual.jsx +29 -0
  115. package/components/brand/BrandVisual.vue +34 -0
  116. package/components/brand/_dir.card.html +13 -0
  117. package/components/brand/brandMotifs.js +210 -0
  118. package/components/buttons/ActionChip.d.ts +10 -0
  119. package/components/buttons/ActionChip.jsx +20 -0
  120. package/components/buttons/ActionChip.vue +18 -0
  121. package/components/buttons/Button.d.ts +40 -0
  122. package/components/buttons/Button.jsx +101 -0
  123. package/components/buttons/Button.vue +87 -0
  124. package/components/buttons/IconButton.d.ts +26 -0
  125. package/components/buttons/IconButton.jsx +28 -0
  126. package/components/buttons/IconButton.vue +21 -0
  127. package/components/buttons/_dir.card.html +13 -0
  128. package/components/buttons/buttons.prompt.md +19 -0
  129. package/components/charts/Bar3D.d.ts +15 -0
  130. package/components/charts/Bar3D.jsx +93 -0
  131. package/components/charts/Bar3D.vue +79 -0
  132. package/components/charts/BarChart.d.ts +23 -0
  133. package/components/charts/BarChart.jsx +135 -0
  134. package/components/charts/BarChart.vue +139 -0
  135. package/components/charts/BarList.d.ts +13 -0
  136. package/components/charts/BarList.jsx +31 -0
  137. package/components/charts/BarList.vue +25 -0
  138. package/components/charts/BoxPlot.d.ts +18 -0
  139. package/components/charts/BoxPlot.jsx +62 -0
  140. package/components/charts/BoxPlot.vue +58 -0
  141. package/components/charts/BulletChart.d.ts +12 -0
  142. package/components/charts/BulletChart.jsx +41 -0
  143. package/components/charts/BulletChart.vue +33 -0
  144. package/components/charts/CandlestickChart.d.ts +15 -0
  145. package/components/charts/CandlestickChart.jsx +63 -0
  146. package/components/charts/CandlestickChart.vue +62 -0
  147. package/components/charts/ChartKit.d.ts +8 -0
  148. package/components/charts/ChartKit.jsx +76 -0
  149. package/components/charts/ChartKit.vue +47 -0
  150. package/components/charts/ChordChart.d.ts +13 -0
  151. package/components/charts/ChordChart.jsx +55 -0
  152. package/components/charts/ChordChart.vue +54 -0
  153. package/components/charts/DonutChart.d.ts +15 -0
  154. package/components/charts/DonutChart.jsx +73 -0
  155. package/components/charts/DonutChart.vue +61 -0
  156. package/components/charts/FunnelChart.d.ts +11 -0
  157. package/components/charts/FunnelChart.jsx +37 -0
  158. package/components/charts/FunnelChart.vue +29 -0
  159. package/components/charts/GanttChart.d.ts +20 -0
  160. package/components/charts/GanttChart.jsx +80 -0
  161. package/components/charts/GanttChart.vue +60 -0
  162. package/components/charts/GaugeChart.d.ts +13 -0
  163. package/components/charts/GaugeChart.jsx +33 -0
  164. package/components/charts/GaugeChart.vue +29 -0
  165. package/components/charts/HeatmapChart.d.ts +13 -0
  166. package/components/charts/HeatmapChart.jsx +62 -0
  167. package/components/charts/HeatmapChart.vue +38 -0
  168. package/components/charts/Histogram.d.ts +16 -0
  169. package/components/charts/Histogram.jsx +56 -0
  170. package/components/charts/Histogram.vue +53 -0
  171. package/components/charts/LineChart.d.ts +17 -0
  172. package/components/charts/LineChart.jsx +84 -0
  173. package/components/charts/LineChart.vue +86 -0
  174. package/components/charts/ParetoChart.d.ts +13 -0
  175. package/components/charts/ParetoChart.jsx +54 -0
  176. package/components/charts/ParetoChart.vue +55 -0
  177. package/components/charts/Pie3D.d.ts +17 -0
  178. package/components/charts/Pie3D.jsx +145 -0
  179. package/components/charts/Pie3D.vue +115 -0
  180. package/components/charts/RadarChart.d.ts +14 -0
  181. package/components/charts/RadarChart.jsx +79 -0
  182. package/components/charts/RadarChart.vue +73 -0
  183. package/components/charts/Ribbon3D.d.ts +13 -0
  184. package/components/charts/Ribbon3D.jsx +89 -0
  185. package/components/charts/Ribbon3D.vue +79 -0
  186. package/components/charts/SankeyChart.d.ts +15 -0
  187. package/components/charts/SankeyChart.jsx +59 -0
  188. package/components/charts/SankeyChart.vue +53 -0
  189. package/components/charts/Scatter3D.d.ts +12 -0
  190. package/components/charts/Scatter3D.jsx +69 -0
  191. package/components/charts/Scatter3D.vue +59 -0
  192. package/components/charts/ScatterChart.d.ts +12 -0
  193. package/components/charts/ScatterChart.jsx +53 -0
  194. package/components/charts/ScatterChart.vue +57 -0
  195. package/components/charts/Sparkline.d.ts +19 -0
  196. package/components/charts/Sparkline.jsx +63 -0
  197. package/components/charts/Sparkline.vue +54 -0
  198. package/components/charts/SunburstChart.d.ts +12 -0
  199. package/components/charts/SunburstChart.jsx +61 -0
  200. package/components/charts/SunburstChart.vue +60 -0
  201. package/components/charts/Surface3D.d.ts +13 -0
  202. package/components/charts/Surface3D.jsx +70 -0
  203. package/components/charts/Surface3D.vue +63 -0
  204. package/components/charts/TreemapChart.d.ts +11 -0
  205. package/components/charts/TreemapChart.jsx +35 -0
  206. package/components/charts/TreemapChart.vue +27 -0
  207. package/components/charts/WaterfallChart.d.ts +11 -0
  208. package/components/charts/WaterfallChart.jsx +59 -0
  209. package/components/charts/WaterfallChart.vue +46 -0
  210. package/components/charts/WorldMap.d.ts +21 -0
  211. package/components/charts/WorldMap.jsx +107 -0
  212. package/components/charts/WorldMap.vue +73 -0
  213. package/components/charts/_dir.card.html +7 -0
  214. package/components/charts/chart-3d.js +84 -0
  215. package/components/charts/chart-geometry.js +223 -0
  216. package/components/charts/charts.prompt.md +24 -0
  217. package/components/data/CodeBlock.d.ts +9 -0
  218. package/components/data/CodeBlock.jsx +19 -0
  219. package/components/data/CodeBlock.vue +22 -0
  220. package/components/data/DataTable.d.ts +28 -0
  221. package/components/data/DataTable.jsx +32 -0
  222. package/components/data/DataTable.vue +25 -0
  223. package/components/data/DiffValue.d.ts +11 -0
  224. package/components/data/DiffValue.jsx +15 -0
  225. package/components/data/DiffValue.vue +13 -0
  226. package/components/data/FilterBar.d.ts +16 -0
  227. package/components/data/FilterBar.jsx +22 -0
  228. package/components/data/FilterBar.vue +23 -0
  229. package/components/data/KeyValue.d.ts +16 -0
  230. package/components/data/KeyValue.jsx +25 -0
  231. package/components/data/KeyValue.vue +26 -0
  232. package/components/data/ListRow.d.ts +14 -0
  233. package/components/data/ListRow.jsx +25 -0
  234. package/components/data/ListRow.vue +25 -0
  235. package/components/data/Pagination.d.ts +12 -0
  236. package/components/data/Pagination.jsx +27 -0
  237. package/components/data/Pagination.vue +24 -0
  238. package/components/data/SmartTable.d.ts +30 -0
  239. package/components/data/SmartTable.jsx +73 -0
  240. package/components/data/SmartTable.vue +74 -0
  241. package/components/data/Spreadsheet.d.ts +33 -0
  242. package/components/data/Spreadsheet.jsx +110 -0
  243. package/components/data/Spreadsheet.vue +95 -0
  244. package/components/data/_dir.card.html +13 -0
  245. package/components/data/data.prompt.md +33 -0
  246. package/components/display/Avatar.d.ts +21 -0
  247. package/components/display/Avatar.jsx +31 -0
  248. package/components/display/Avatar.vue +34 -0
  249. package/components/display/Badge.d.ts +27 -0
  250. package/components/display/Badge.jsx +40 -0
  251. package/components/display/Badge.vue +47 -0
  252. package/components/display/Card.d.ts +27 -0
  253. package/components/display/Card.jsx +27 -0
  254. package/components/display/Card.vue +28 -0
  255. package/components/display/Divider.d.ts +8 -0
  256. package/components/display/Divider.jsx +14 -0
  257. package/components/display/Divider.vue +13 -0
  258. package/components/display/Kbd.d.ts +7 -0
  259. package/components/display/Kbd.jsx +12 -0
  260. package/components/display/Kbd.vue +9 -0
  261. package/components/display/ProgressBar.d.ts +42 -0
  262. package/components/display/ProgressBar.jsx +70 -0
  263. package/components/display/ProgressBar.vue +69 -0
  264. package/components/display/Tag.d.ts +9 -0
  265. package/components/display/Tag.jsx +15 -0
  266. package/components/display/Tag.vue +15 -0
  267. package/components/display/_dir.card.html +13 -0
  268. package/components/display/display.prompt.md +30 -0
  269. package/components/feedback/Accordion.d.ts +13 -0
  270. package/components/feedback/Accordion.jsx +21 -0
  271. package/components/feedback/Accordion.vue +22 -0
  272. package/components/feedback/ActivityItem.d.ts +25 -0
  273. package/components/feedback/ActivityItem.jsx +39 -0
  274. package/components/feedback/ActivityItem.vue +46 -0
  275. package/components/feedback/Alert.d.ts +36 -0
  276. package/components/feedback/Alert.jsx +48 -0
  277. package/components/feedback/Alert.vue +59 -0
  278. package/components/feedback/Banner.d.ts +15 -0
  279. package/components/feedback/Banner.jsx +25 -0
  280. package/components/feedback/Banner.vue +25 -0
  281. package/components/feedback/ContextMenu.d.ts +8 -0
  282. package/components/feedback/ContextMenu.jsx +18 -0
  283. package/components/feedback/ContextMenu.vue +19 -0
  284. package/components/feedback/Drawer.d.ts +18 -0
  285. package/components/feedback/Drawer.jsx +26 -0
  286. package/components/feedback/Drawer.vue +24 -0
  287. package/components/feedback/Menu.d.ts +10 -0
  288. package/components/feedback/Menu.jsx +24 -0
  289. package/components/feedback/Menu.vue +21 -0
  290. package/components/feedback/Modal.d.ts +38 -0
  291. package/components/feedback/Modal.jsx +69 -0
  292. package/components/feedback/Modal.vue +65 -0
  293. package/components/feedback/Stepper.d.ts +9 -0
  294. package/components/feedback/Stepper.jsx +24 -0
  295. package/components/feedback/Stepper.vue +18 -0
  296. package/components/feedback/Timeline.d.ts +15 -0
  297. package/components/feedback/Timeline.jsx +27 -0
  298. package/components/feedback/Timeline.vue +21 -0
  299. package/components/feedback/_dir.card.html +13 -0
  300. package/components/feedback/feedback.prompt.md +35 -0
  301. package/components/forms/Checkbox.d.ts +13 -0
  302. package/components/forms/Checkbox.jsx +17 -0
  303. package/components/forms/Checkbox.vue +18 -0
  304. package/components/forms/Combobox.d.ts +13 -0
  305. package/components/forms/Combobox.jsx +34 -0
  306. package/components/forms/Combobox.vue +35 -0
  307. package/components/forms/DatePicker.d.ts +12 -0
  308. package/components/forms/DatePicker.jsx +48 -0
  309. package/components/forms/DatePicker.vue +46 -0
  310. package/components/forms/Dropzone.d.ts +20 -0
  311. package/components/forms/Dropzone.jsx +36 -0
  312. package/components/forms/Dropzone.vue +28 -0
  313. package/components/forms/Field.d.ts +13 -0
  314. package/components/forms/Field.jsx +13 -0
  315. package/components/forms/Field.vue +12 -0
  316. package/components/forms/Input.d.ts +18 -0
  317. package/components/forms/Input.jsx +35 -0
  318. package/components/forms/Input.vue +38 -0
  319. package/components/forms/MultiSelect.d.ts +14 -0
  320. package/components/forms/MultiSelect.jsx +33 -0
  321. package/components/forms/MultiSelect.vue +36 -0
  322. package/components/forms/NumberStepper.d.ts +13 -0
  323. package/components/forms/NumberStepper.jsx +15 -0
  324. package/components/forms/NumberStepper.vue +17 -0
  325. package/components/forms/Radio.vue +16 -0
  326. package/components/forms/RadioGroup.vue +11 -0
  327. package/components/forms/SearchInput.d.ts +12 -0
  328. package/components/forms/SearchInput.jsx +17 -0
  329. package/components/forms/SearchInput.vue +14 -0
  330. package/components/forms/Select.d.ts +14 -0
  331. package/components/forms/Select.jsx +17 -0
  332. package/components/forms/Select.vue +16 -0
  333. package/components/forms/Slider.d.ts +15 -0
  334. package/components/forms/Slider.jsx +21 -0
  335. package/components/forms/Slider.vue +23 -0
  336. package/components/forms/Switch.d.ts +31 -0
  337. package/components/forms/Switch.jsx +40 -0
  338. package/components/forms/Switch.vue +16 -0
  339. package/components/forms/_dir.card.html +13 -0
  340. package/components/forms/forms.prompt.md +23 -0
  341. package/components/icons/Icon.d.ts +19 -0
  342. package/components/icons/Icon.jsx +93 -0
  343. package/components/icons/Icon.prompt.md +8 -0
  344. package/components/icons/Icon.vue +12 -0
  345. package/components/icons/Unicon.d.ts +12 -0
  346. package/components/icons/Unicon.jsx +16 -0
  347. package/components/icons/Unicon.vue +15 -0
  348. package/components/icons/_dir.card.html +13 -0
  349. package/components/icons/feather-paths.js +2 -0
  350. package/components/icons/icon-paths.js +73 -0
  351. package/components/index.d.ts +87 -0
  352. package/components/index.js +110 -0
  353. package/components/navigation/Breadcrumb.d.ts +24 -0
  354. package/components/navigation/Breadcrumb.jsx +120 -0
  355. package/components/navigation/Breadcrumb.vue +94 -0
  356. package/components/navigation/DocTree.d.ts +18 -0
  357. package/components/navigation/DocTree.jsx +37 -0
  358. package/components/navigation/DocTree.vue +25 -0
  359. package/components/navigation/Sidebar.d.ts +29 -0
  360. package/components/navigation/Sidebar.jsx +75 -0
  361. package/components/navigation/Sidebar.vue +54 -0
  362. package/components/navigation/TopBar.d.ts +27 -0
  363. package/components/navigation/TopBar.jsx +44 -0
  364. package/components/navigation/TopBar.vue +51 -0
  365. package/components/navigation/Tree.d.ts +83 -0
  366. package/components/navigation/Tree.jsx +347 -0
  367. package/components/navigation/Tree.vue +258 -0
  368. package/components/navigation/_dir.card.html +13 -0
  369. package/components/navigation/navigation.prompt.md +22 -0
  370. package/components/pipeline/ConfigPanel.d.ts +18 -0
  371. package/components/pipeline/ConfigPanel.jsx +30 -0
  372. package/components/pipeline/ConfigPanel.vue +32 -0
  373. package/components/pipeline/DataPreview.d.ts +14 -0
  374. package/components/pipeline/DataPreview.jsx +24 -0
  375. package/components/pipeline/DataPreview.vue +21 -0
  376. package/components/pipeline/NodeCard.d.ts +47 -0
  377. package/components/pipeline/NodeCard.jsx +97 -0
  378. package/components/pipeline/NodeCard.vue +75 -0
  379. package/components/pipeline/PaletteItem.vue +15 -0
  380. package/components/pipeline/PaletteListItem.vue +15 -0
  381. package/components/pipeline/PalettePanel.d.ts +20 -0
  382. package/components/pipeline/PalettePanel.jsx +74 -0
  383. package/components/pipeline/PalettePanel.vue +45 -0
  384. package/components/pipeline/PipelineCanvas.d.ts +25 -0
  385. package/components/pipeline/PipelineCanvas.jsx +94 -0
  386. package/components/pipeline/PipelineCanvas.vue +73 -0
  387. package/components/pipeline/ZoomControls.d.ts +9 -0
  388. package/components/pipeline/ZoomControls.jsx +15 -0
  389. package/components/pipeline/ZoomControls.vue +15 -0
  390. package/components/pipeline/_dir.card.html +13 -0
  391. package/components/pipeline/pipeline.prompt.md +22 -0
  392. package/components/tabs/SegmentedControl.d.ts +11 -0
  393. package/components/tabs/SegmentedControl.jsx +21 -0
  394. package/components/tabs/SegmentedControl.vue +15 -0
  395. package/components/tabs/Tabs.d.ts +13 -0
  396. package/components/tabs/Tabs.jsx +52 -0
  397. package/components/tabs/Tabs.vue +39 -0
  398. package/components/tabs/ViewToggle.d.ts +8 -0
  399. package/components/tabs/ViewToggle.jsx +12 -0
  400. package/components/tabs/ViewToggle.vue +12 -0
  401. package/components/tabs/_dir.card.html +13 -0
  402. package/components/tabs/tabs.prompt.md +14 -0
  403. package/package.json +76 -0
  404. package/readme.md +150 -0
  405. package/styles.css +10 -0
  406. package/tokens/alpha.css +27 -0
  407. package/tokens/charts.css +55 -0
  408. package/tokens/colors-extended.css +40 -0
  409. package/tokens/colors.css +39 -0
  410. package/tokens/dark.css +96 -0
  411. package/tokens/fonts.css +4 -0
  412. package/tokens/interaction.css +48 -0
  413. package/tokens/layout.css +30 -0
  414. package/tokens/motion.css +22 -0
  415. package/tokens/tokens.d.ts +680 -0
  416. package/tokens/tokens.js +1018 -0
  417. package/tokens/tokens.json +2928 -0
  418. package/tokens/typography.css +22 -0
@@ -0,0 +1,75 @@
1
+ <script setup>
2
+ import { ref } from 'vue'
3
+ import Icon from '../icons/Icon.vue'
4
+ import { IconTile, StatusBadge } from '../display/Badge.vue'
5
+ /**
6
+ * Canvas node card — 220×90, r16, soft shadow. Selected = blue border + blue-100 ring.
7
+ * badge: "error" | "warning" | "clock" overlay on the icon tile.
8
+ * Ports light up on hover, stay lit while a wire is dragged out (outputTone="active"),
9
+ * and show a crosshair when they are a valid drop target (inputTones[i]="target").
10
+ */
11
+ const props = defineProps({ title: String, subtitle: String, icon: { type: String, default: 'table' }, subtitleIcon: { type: [String, Boolean], default: 'info' }, hue: { type: String, default: 'source' }, selected: Boolean, badge: String, inputs: { type: Array, default: () => [] }, output: { type: Boolean, default: true }, showMenu: { type: Boolean, default: true }, live: Boolean, outputTone: { type: String, default: 'default' }, inputTones: { type: Array, default: () => [] }, style: Object })
12
+ const emit = defineEmits(['click', 'menu', 'outputDown', 'inputUp', 'inputEnter', 'inputLeave'])
13
+ const hoverOut = ref(false)
14
+ const hoverIn = ref(-1)
15
+ function skin(tone, hover) {
16
+ const hot = tone === 'active' || tone === 'target' || (props.live && hover)
17
+ return {
18
+ background: tone === 'target' ? 'var(--soft-bg)' : 'var(--bg-surface)',
19
+ border: `2px solid ${hot ? 'var(--action-primary)' : 'var(--port-border)'}`,
20
+ boxShadow: tone === 'active' || tone === 'target' ? '0 0 0 3px var(--focus-ring)' : 'none',
21
+ color: hot ? 'var(--action-primary)' : 'var(--text-muted)',
22
+ cursor: props.live ? (tone === 'active' ? 'grabbing' : 'grab') : 'default',
23
+ transition: 'var(--t-hover)',
24
+ }
25
+ }
26
+ const portBase = { width: '22px', height: '22px', borderRadius: 'var(--radius-full)', boxSizing: 'border-box', display: 'inline-flex', alignItems: 'center', justifyContent: 'center' }
27
+ const pillBase = { width: '28px', height: '22px', borderRadius: 'var(--radius-full)', boxSizing: 'border-box', display: 'inline-flex', alignItems: 'center', justifyContent: 'center', gap: '2px', fontFamily: 'var(--font-sans)', fontSize: 'var(--text-xs)', letterSpacing: 'var(--tracking-xs)', lineHeight: 1 }
28
+ const tone = i => props.inputTones[i] || 'default'
29
+ </script>
30
+ <template>
31
+ <div @click="emit('click')" :style="{ position: 'relative', width: '220px', height: '90px', borderRadius: 'var(--radius-node)', background: 'var(--bg-surface)', border: `1px solid ${selected ? 'var(--selected-border)' : 'var(--border-control)'}`, boxShadow: selected ? 'var(--shadow-selected)' : 'var(--shadow-node)', boxSizing: 'border-box', cursor: 'pointer', ...style }">
32
+ <div style="display:flex;align-items:center;gap:12px;padding:16px;height:100%;box-sizing:border-box">
33
+ <span style="position:relative;flex-shrink:0">
34
+ <IconTile :icon="icon" :hue="hue" kind="node" />
35
+ <StatusBadge v-if="badge === 'error'" tone="danger" icon="bug" :size="20" style="position:absolute;top:-6px;right:-6px" />
36
+ <StatusBadge v-if="badge === 'warning'" tone="warning" icon="triangle-alert" :size="20" style="position:absolute;top:-6px;right:-6px" />
37
+ <StatusBadge v-if="badge === 'clock'" tone="pending" icon="clock" :size="20" style="position:absolute;top:-6px;right:-6px" />
38
+ </span>
39
+ <div style="display:flex;flex-direction:column;min-width:0;flex:1;padding-right:18px">
40
+ <span style="font-family:var(--font-sans);font-weight:var(--weight-semibold);font-size:var(--text-base);line-height:17.875px;letter-spacing:var(--tracking-base);color:var(--text-heading);white-space:nowrap;overflow:hidden;text-overflow:ellipsis">{{ title }}</span>
41
+ <span style="display:flex;align-items:flex-start;gap:4px;padding-top:4px;min-width:0">
42
+ <span v-if="subtitleIcon !== false" style="color:var(--text-muted);display:inline-flex;flex-shrink:0;padding-top:1px"><Icon :name="subtitleIcon || 'info'" :size="13" /></span>
43
+ <!-- Node types run long ("Field Value Calculation"): wrap to a second line, then clamp. -->
44
+ <span style="font-family:var(--font-sans);font-size:var(--text-xs);line-height:13.75px;letter-spacing:var(--tracking-xs);color:var(--text-muted);min-width:0;overflow:hidden;display:-webkit-box;-webkit-box-orient:vertical;-webkit-line-clamp:2;overflow-wrap:break-word">{{ subtitle }}</span>
45
+ </span>
46
+ </div>
47
+ </div>
48
+ <button v-if="showMenu" type="button" @click.stop="emit('menu', $event)" class="kb-node-menu" style="position:absolute;top:10px;right:12px;width:23px;height:23px;border-radius:var(--radius-md);border:none;background:transparent;cursor:pointer;display:flex;align-items:center;justify-content:center;color:var(--text-muted);padding:0">
49
+ <Icon name="ellipsis" :size="15" />
50
+ </button>
51
+ <template v-if="inputs.length">
52
+ <span v-if="inputs.length === 1 && !inputs[0]"
53
+ @mouseenter="hoverIn = 0; emit('inputEnter', 0)" @mouseleave="hoverIn = -1; emit('inputLeave', 0)"
54
+ @pointerup="emit('inputUp', 0, $event)"
55
+ :style="{ ...portBase, ...skin(tone(0), hoverIn === 0), position: 'absolute', left: '-11px', top: '33px' }">
56
+ <Icon :name="tone(0) === 'target' ? 'plus' : 'arrow-right'" :size="12" :stroke-width="2.2" />
57
+ </span>
58
+ <span v-else v-for="(l, i) in inputs" :key="i"
59
+ @mouseenter="hoverIn = i; emit('inputEnter', i)" @mouseleave="hoverIn = -1; emit('inputLeave', i)"
60
+ @pointerup="emit('inputUp', i, $event)"
61
+ :style="{ ...pillBase, ...skin(tone(i), hoverIn === i), position: 'absolute', left: '-14px', top: (inputs.length === 1 ? 33 : 12 + i * 38) + 'px' }">
62
+ <Icon v-if="tone(i) === 'target'" name="plus" :size="12" :stroke-width="2.2" />
63
+ <template v-else>{{ l }}<Icon name="chevron-right" :size="9" :stroke-width="2.5" /></template>
64
+ </span>
65
+ </template>
66
+ <span v-if="output" @mouseenter="hoverOut = true" @mouseleave="hoverOut = false"
67
+ @pointerdown.stop="emit('outputDown', $event)" @click.stop
68
+ :style="{ ...portBase, ...skin(outputTone, hoverOut), position: 'absolute', right: '-11px', top: '33px' }">
69
+ <Icon name="arrow-right" :size="12" :stroke-width="2.2" />
70
+ </span>
71
+ </div>
72
+ </template>
73
+ <style scoped>
74
+ .kb-node-menu:hover{background:var(--bg-hover)}
75
+ </style>
@@ -0,0 +1,15 @@
1
+ <script setup>
2
+ import { ref } from 'vue'
3
+ import { IconTile } from '../display/Badge.vue'
4
+ // Palette grid tile — 40px tinted icon + 10px two-line label.
5
+ defineProps({ icon: String, hue: String, label: String, style: Object })
6
+ defineEmits(['click'])
7
+ const hover = ref(false)
8
+ </script>
9
+ <template>
10
+ <div role="button" tabindex="0" @click="$emit('click')" @mouseenter="hover = true" @mouseleave="hover = false"
11
+ :style="{ width: 67.664, borderRadius: 'var(--radius-lg)', padding: 8, display: 'flex', flexDirection: 'column', gap: 6, alignItems: 'center', cursor: 'grab', boxSizing: 'border-box', background: hover ? 'var(--bg-hover)' : 'transparent', transition: 'background .12s ease', ...style }">
12
+ <IconTile :icon="icon" :hue="hue" kind="palette" />
13
+ <span style="font-family:var(--font-sans);font-size:var(--text-2xs);line-height:var(--leading-2xs);letter-spacing:var(--tracking-2xs);color:var(--text-body);text-align:center">{{ label }}</span>
14
+ </div>
15
+ </template>
@@ -0,0 +1,15 @@
1
+ <script setup>
2
+ import { ref } from 'vue'
3
+ import Icon from '../icons/Icon.vue'
4
+ // Palette list row — 14px hued glyph + 13px label, indented under its category.
5
+ defineProps({ icon: String, hue: String, label: String, style: Object })
6
+ defineEmits(['click'])
7
+ const hover = ref(false)
8
+ </script>
9
+ <template>
10
+ <div role="button" tabindex="0" @click="$emit('click')" @mouseenter="hover = true" @mouseleave="hover = false"
11
+ :style="{ height: 'var(--h-subnav-item)', borderRadius: 'var(--radius-md)', display: 'flex', alignItems: 'center', gap: 8, padding: '6px 8px', boxSizing: 'border-box', cursor: 'grab', background: hover ? 'var(--bg-hover)' : 'transparent', ...style }">
12
+ <span :style="{ color: `var(--cat-${hue})`, display: 'inline-flex' }"><Icon :name="icon" :size="14" /></span>
13
+ <span style="font-family:var(--font-sans);font-size:var(--text-base);line-height:var(--leading-base);letter-spacing:var(--tracking-base);color:var(--text-body);white-space:nowrap">{{ label }}</span>
14
+ </div>
15
+ </template>
@@ -0,0 +1,20 @@
1
+ import * as React from "react";
2
+ export interface PaletteEntry { label: string; icon: string; }
3
+ export interface PaletteCategory { label: string; icon: string; hue: string; items: PaletteEntry[]; }
4
+ /** The file's complete node inventory: Source / Join / Transformation / Merge / Output. */
5
+ export declare const PIPELINE_CATALOG: PaletteCategory[];
6
+ /** Grid tile (40px tinted icon + 10px label). */
7
+ export declare function PaletteItem(props: { icon: string; hue: string; label: string; onClick?: () => void; style?: React.CSSProperties }): JSX.Element;
8
+ /** List row flavor. */
9
+ export declare function PaletteListItem(props: { icon: string; hue: string; label: string; onClick?: () => void; style?: React.CSSProperties }): JSX.Element;
10
+ /**
11
+ * 240px "Components" palette with list/grid toggle + collapsible categories.
12
+ * @startingPoint section="Pipeline" subtitle="Node palette panel (grid + list views)" viewport="240x600"
13
+ */
14
+ export interface PalettePanelProps {
15
+ catalog?: PaletteCategory[];
16
+ height?: number | string;
17
+ onPick?: (category: string, item: string) => void;
18
+ style?: React.CSSProperties;
19
+ }
20
+ export declare function PalettePanel(props: PalettePanelProps): JSX.Element;
@@ -0,0 +1,74 @@
1
+ import React from "react";
2
+ import { Icon } from "../icons/Icon.jsx";
3
+ import { IconTile } from "../display/Badge.jsx";
4
+ import { ViewToggle } from "../tabs/ViewToggle.jsx";
5
+
6
+ /** Palette grid tile — 40px tinted icon + 10px two-line label. */
7
+ export function PaletteItem({ icon, hue, label, onClick, style }) {
8
+ const [hover, setHover] = React.useState(false);
9
+ return (
10
+ <div role="button" tabIndex={0} onClick={onClick} onMouseEnter={() => setHover(true)} onMouseLeave={() => setHover(false)}
11
+ style={{ width: 67.664, borderRadius: "var(--radius-lg)", padding: 8, display: "flex", flexDirection: "column", gap: 6, alignItems: "center", cursor: "grab", boxSizing: "border-box", background: hover ? "var(--bg-hover)" : "transparent", transition: "background .12s ease", ...style }}>
12
+ <IconTile icon={icon} hue={hue} kind="palette" />
13
+ <span style={{ fontFamily: "var(--font-sans)", fontSize: "var(--text-2xs)", lineHeight: "var(--leading-2xs)", letterSpacing: "var(--tracking-2xs)", color: "var(--text-body)", textAlign: "center" }}>{label}</span>
14
+ </div>
15
+ );
16
+ }
17
+
18
+ /** Palette list row — 14px hued glyph + 13px label, indented under its category. */
19
+ export function PaletteListItem({ icon, hue, label, onClick, style }) {
20
+ const [hover, setHover] = React.useState(false);
21
+ return (
22
+ <div role="button" tabIndex={0} onClick={onClick} onMouseEnter={() => setHover(true)} onMouseLeave={() => setHover(false)}
23
+ style={{ height: "var(--h-subnav-item)", borderRadius: "var(--radius-md)", display: "flex", alignItems: "center", gap: 8, padding: "6px 8px", boxSizing: "border-box", cursor: "grab", background: hover ? "var(--bg-hover)" : "transparent", ...style }}>
24
+ <span style={{ color: `var(--cat-${hue})`, display: "inline-flex" }}><Icon name={icon} size={14} /></span>
25
+ <span style={{ fontFamily: "var(--font-sans)", fontSize: "var(--text-base)", lineHeight: "var(--leading-base)", letterSpacing: "var(--tracking-base)", color: "var(--text-body)", whiteSpace: "nowrap" }}>{label}</span>
26
+ </div>
27
+ );
28
+ }
29
+
30
+ /** The full component set of the pipeline editor, verbatim from the file. */
31
+ export const PIPELINE_CATALOG = [
32
+ { label: "Data Source", icon: "table", hue: "source", items: [{ label: "Detail Sheet", icon: "table" }, { label: "Model", icon: "layers" }, { label: "Dimension", icon: "grid-3x3" }] },
33
+ { label: "Data Join", icon: "text-search", hue: "join", items: [{ label: "Lookup Data", icon: "text-search" }, { label: "Association Match", icon: "shuffle" }] },
34
+ { label: "Data Transformation", icon: "sliders-horizontal", hue: "transform", items: [{ label: "Field Value Calculation", icon: "sliders-horizontal" }, { label: "Field Split", icon: "split" }, { label: "Row to Column", icon: "arrow-right-left" }, { label: "Column to Row", icon: "menu" }, { label: "Multi-Condition Judge", icon: "funnel" }, { label: "Regional Calculation", icon: "chart-no-axes-column" }, { label: "Advanced Transformation", icon: "trending-up" }, { label: "JS Enhanced Processing", icon: "code" }] },
35
+ { label: "Data Merge", icon: "database", hue: "merge", items: [{ label: "Group Calculation", icon: "database" }, { label: "Concat Merge", icon: "merge" }] },
36
+ { label: "Data Output", icon: "table", hue: "output", items: [{ label: "Detail Sheet", icon: "table" }, { label: "Model", icon: "layers" }, { label: "Dimension", icon: "grid-3x3" }] },
37
+ ];
38
+
39
+ /** 240px "Components" palette panel with list/grid toggle and collapsible hued categories. */
40
+ export function PalettePanel({ catalog = PIPELINE_CATALOG, height = "100%", onPick, style }) {
41
+ const [view, setView] = React.useState("grid");
42
+ const [closed, setClosed] = React.useState([]);
43
+ const toggle = (l) => setClosed(closed.includes(l) ? closed.filter((x) => x !== l) : [...closed, l]);
44
+ return (
45
+ <div style={{ width: "var(--sidebar-w)", height, background: "var(--bg-surface)", borderRight: "1px solid var(--border-card)", display: "flex", flexDirection: "column", boxSizing: "border-box", flexShrink: 0, ...style }}>
46
+ <div style={{ height: 43, borderBottom: "1px solid var(--border-subtle)", display: "flex", alignItems: "center", justifyContent: "space-between", padding: "8px 12px", boxSizing: "border-box", flexShrink: 0 }}>
47
+ <span style={{ fontFamily: "var(--font-sans)", fontSize: "var(--text-base)", lineHeight: "var(--leading-base)", letterSpacing: "var(--tracking-base)", color: "var(--text-body)" }}>Components</span>
48
+ <ViewToggle value={view} onChange={setView} />
49
+ </div>
50
+ <div style={{ flex: 1, overflowY: "auto", padding: 8 }}>
51
+ {catalog.map((cat) => (
52
+ <div key={cat.label}>
53
+ <div onClick={() => toggle(cat.label)} style={{ height: "var(--h-subnav-item)", borderRadius: "var(--radius-md)", display: "flex", alignItems: "center", gap: 8, padding: "6px 8px", boxSizing: "border-box", cursor: "pointer" }}>
54
+ <span style={{ color: "var(--text-muted)", display: "inline-flex", transform: closed.includes(cat.label) ? "rotate(-90deg)" : "none", transition: "transform .15s ease" }}><Icon name="chevron-down" size={14} /></span>
55
+ <span style={{ color: `var(--cat-${cat.hue})`, display: "inline-flex" }}><Icon name={cat.icon} size={14} /></span>
56
+ <span style={{ fontFamily: "var(--font-sans)", fontWeight: "var(--weight-medium)", fontSize: "var(--text-base)", lineHeight: "var(--leading-base)", letterSpacing: "var(--tracking-base)", color: "var(--text-strong)" }}>{cat.label}</span>
57
+ </div>
58
+ {!closed.includes(cat.label) ? (
59
+ view === "grid" ? (
60
+ <div style={{ display: "flex", flexWrap: "wrap", padding: "8px 0 8px 4px" }}>
61
+ {cat.items.map((it) => <PaletteItem key={it.label} icon={it.icon} hue={cat.hue} label={it.label} onClick={() => onPick && onPick(cat.label, it.label)} />)}
62
+ </div>
63
+ ) : (
64
+ <div style={{ padding: "2px 0 6px 20px", display: "flex", flexDirection: "column" }}>
65
+ {cat.items.map((it) => <PaletteListItem key={it.label} icon={it.icon} hue={cat.hue} label={it.label} onClick={() => onPick && onPick(cat.label, it.label)} />)}
66
+ </div>
67
+ )
68
+ ) : null}
69
+ </div>
70
+ ))}
71
+ </div>
72
+ </div>
73
+ );
74
+ }
@@ -0,0 +1,45 @@
1
+ <script setup>
2
+ import { ref } from 'vue'
3
+ import Icon from '../icons/Icon.vue'
4
+ import { IconTile } from '../display/Badge.vue'
5
+ import ViewToggle from '../tabs/ViewToggle.vue'
6
+ import PaletteItem from './PaletteItem.vue'
7
+ import PaletteListItem from './PaletteListItem.vue'
8
+
9
+ export const PIPELINE_CATALOG = [
10
+ { label: 'Data Source', icon: 'table', hue: 'source', items: [{ label: 'Detail Sheet', icon: 'table' }, { label: 'Model', icon: 'layers' }, { label: 'Dimension', icon: 'grid-3x3' }] },
11
+ { label: 'Data Join', icon: 'text-search', hue: 'join', items: [{ label: 'Lookup Data', icon: 'text-search' }, { label: 'Association Match', icon: 'shuffle' }] },
12
+ { label: 'Data Transformation', icon: 'sliders-horizontal', hue: 'transform', items: [{ label: 'Field Value Calculation', icon: 'sliders-horizontal' }, { label: 'Field Split', icon: 'split' }, { label: 'Row to Column', icon: 'arrow-right-left' }, { label: 'Column to Row', icon: 'menu' }, { label: 'Multi-Condition Judge', icon: 'funnel' }, { label: 'Regional Calculation', icon: 'chart-no-axes-column' }, { label: 'Advanced Transformation', icon: 'trending-up' }, { label: 'JS Enhanced Processing', icon: 'code' }] },
13
+ { label: 'Data Merge', icon: 'database', hue: 'merge', items: [{ label: 'Group Calculation', icon: 'database' }, { label: 'Concat Merge', icon: 'merge' }] },
14
+ { label: 'Data Output', icon: 'table', hue: 'output', items: [{ label: 'Detail Sheet', icon: 'table' }, { label: 'Model', icon: 'layers' }, { label: 'Dimension', icon: 'grid-3x3' }] },
15
+ ]
16
+ // 240px "Components" palette panel with list/grid toggle and collapsible hued categories.
17
+ const props = defineProps({ catalog: { type: Array, default: () => PIPELINE_CATALOG }, height: { type: [String, Number], default: '100%' }, style: Object })
18
+ const emit = defineEmits(['pick'])
19
+ const view = ref('grid')
20
+ const closed = ref([])
21
+ function toggle(l) { closed.value = closed.value.includes(l) ? closed.value.filter(x => x !== l) : [...closed.value, l] }
22
+ </script>
23
+ <template>
24
+ <div :style="{ width: 'var(--sidebar-w)', height, background: 'var(--bg-surface)', borderRight: '1px solid var(--border-card)', display: 'flex', flexDirection: 'column', boxSizing: 'border-box', flexShrink: 0, ...style }">
25
+ <div style="height:43px;border-bottom:1px solid var(--border-subtle);display:flex;align-items:center;justify-content:space-between;padding:8px 12px;box-sizing:border-box;flex-shrink:0">
26
+ <span style="font-family:var(--font-sans);font-size:var(--text-base);line-height:var(--leading-base);letter-spacing:var(--tracking-base);color:var(--text-body)">Components</span>
27
+ <ViewToggle v-model="view" />
28
+ </div>
29
+ <div style="flex:1;overflow-y:auto;padding:8px">
30
+ <div v-for="cat in catalog" :key="cat.label">
31
+ <div @click="toggle(cat.label)" style="height:var(--h-subnav-item);border-radius:var(--radius-md);display:flex;align-items:center;gap:8px;padding:6px 8px;box-sizing:border-box;cursor:pointer">
32
+ <span :style="{ color: 'var(--text-muted)', display: 'inline-flex', transform: closed.includes(cat.label) ? 'rotate(-90deg)' : 'none', transition: 'transform .15s ease' }"><Icon name="chevron-down" :size="14" /></span>
33
+ <span :style="{ color: `var(--cat-${cat.hue})`, display: 'inline-flex' }"><Icon :name="cat.icon" :size="14" /></span>
34
+ <span style="font-family:var(--font-sans);font-weight:var(--weight-medium);font-size:var(--text-base);line-height:var(--leading-base);letter-spacing:var(--tracking-base);color:var(--text-strong)">{{ cat.label }}</span>
35
+ </div>
36
+ <div v-if="!closed.includes(cat.label) && view === 'grid'" style="display:flex;flex-wrap:wrap;padding:8px 0 8px 4px">
37
+ <PaletteItem v-for="it in cat.items" :key="it.label" :icon="it.icon" :hue="cat.hue" :label="it.label" @click="emit('pick', cat.label, it.label)" />
38
+ </div>
39
+ <div v-else-if="!closed.includes(cat.label)" style="padding:2px 0 6px 20px;display:flex;flex-direction:column">
40
+ <PaletteListItem v-for="it in cat.items" :key="it.label" :icon="it.icon" :hue="cat.hue" :label="it.label" @click="emit('pick', cat.label, it.label)" />
41
+ </div>
42
+ </div>
43
+ </div>
44
+ </div>
45
+ </template>
@@ -0,0 +1,25 @@
1
+ import * as React from "react";
2
+ import { NodeCardProps } from "./NodeCard";
3
+ export interface PipelineNode extends NodeCardProps { id: string; x: number; y: number; }
4
+ export interface PipelineEdge { from: string; to: string; /** input index for A/B ports */ toPort?: number; }
5
+ /**
6
+ * #fafafa canvas with slate-300 bezier edges and positioned NodeCards.
7
+ * @startingPoint section="Pipeline" subtitle="Node canvas with edges" viewport="700x420"
8
+ */
9
+ export interface PipelineCanvasProps {
10
+ nodes?: PipelineNode[];
11
+ edges?: PipelineEdge[];
12
+ selectedId?: string;
13
+ onSelect?: (id: string) => void;
14
+ onMenu?: (id: string, e: React.MouseEvent) => void;
15
+ /** Enables wire dragging: hold an output port, drop on an input port */
16
+ onConnect?: (edge: { from: string; to: string; toPort: number }) => void;
17
+ /** Pointer distance (canvas px) at which a wire snaps to an input port. Default 30 */
18
+ snapRadius?: number;
19
+ /** Current zoom factor, so pointer coordinates map back to canvas space */
20
+ scale?: number;
21
+ width?: number | string;
22
+ height?: number | string;
23
+ style?: React.CSSProperties;
24
+ }
25
+ export declare function PipelineCanvas(props: PipelineCanvasProps): JSX.Element;
@@ -0,0 +1,94 @@
1
+ import React from "react";
2
+ import { NodeCard } from "./NodeCard.jsx";
3
+
4
+ const NODE_W = 220;
5
+ const outPt = (n) => ({ x: n.x + NODE_W, y: n.y + 44 });
6
+ const inPt = (n, portIdx = 0) => {
7
+ const multi = (n.inputs || []).filter(Boolean).length > 1;
8
+ return { x: n.x, y: multi ? n.y + 23 + portIdx * 38 : n.y + 44 };
9
+ };
10
+ /** Horizontal cubic bezier; the control offset keeps a backward link bowed out of the cards. */
11
+ const curve = (p1, p2) => {
12
+ const dx = Math.max(40, (p2.x - p1.x) / 2);
13
+ return `M ${p1.x} ${p1.y} C ${p1.x + dx} ${p1.y}, ${p2.x - dx} ${p2.y}, ${p2.x} ${p2.y}`;
14
+ };
15
+
16
+ /**
17
+ * Pipeline canvas: #fafafa surface, slate bezier edges, absolutely-placed NodeCards.
18
+ * nodes: [{id,x,y,...NodeCardProps}]; edges: [{from,to,toPort}] (toPort index for A/B inputs).
19
+ * With onConnect, holding an output port drags a dashed wire; input ports light up as drop
20
+ * targets and the drop reports {from,to,toPort}. scale tells the canvas its zoom factor so
21
+ * pointer coordinates stay in canvas space.
22
+ */
23
+ export function PipelineCanvas({ nodes = [], edges = [], selectedId, onSelect, onMenu, onConnect, snapRadius = 30, scale = 1, width = "100%", height = "100%", style }) {
24
+ const byId = Object.fromEntries(nodes.map((n) => [n.id, n]));
25
+ const ref = React.useRef(null);
26
+ const [drag, setDrag] = React.useState(null); // {from, x, y, over:{id,port}}
27
+
28
+ /* The drop target is hit-tested from the pointer position rather than port hover:
29
+ during a drag the cursor is often over the wire layer, not the 22px handle. */
30
+ const hitTest = React.useCallback((x, y, fromId) => {
31
+ let best = null;
32
+ nodes.forEach((n) => {
33
+ if (n.id === fromId) return;
34
+ const ports = n.inputs || [];
35
+ if (!ports.length) return;
36
+ ports.forEach((_, i) => {
37
+ const p = inPt(n, i);
38
+ const d = Math.hypot(p.x - x, p.y - y);
39
+ if (d <= snapRadius && (!best || d < best.d)) best = { id: n.id, port: i, d };
40
+ });
41
+ });
42
+ return best ? { id: best.id, port: best.port } : null;
43
+ }, [nodes, snapRadius]);
44
+
45
+ React.useEffect(() => {
46
+ if (!drag) return;
47
+ const move = (e) => {
48
+ const r = ref.current.getBoundingClientRect();
49
+ const x = (e.clientX - r.left) / scale, y = (e.clientY - r.top) / scale;
50
+ setDrag((d) => d && { ...d, x, y, over: hitTest(x, y, d.from) });
51
+ };
52
+ const up = () => setDrag((d) => {
53
+ if (d && d.over && onConnect) onConnect({ from: d.from, to: d.over.id, toPort: d.over.port });
54
+ return null;
55
+ });
56
+ window.addEventListener("pointermove", move);
57
+ window.addEventListener("pointerup", up);
58
+ return () => { window.removeEventListener("pointermove", move); window.removeEventListener("pointerup", up); };
59
+ }, [drag, scale, onConnect, hitTest]);
60
+
61
+ const start = (id, e) => {
62
+ const r = ref.current.getBoundingClientRect();
63
+ setDrag({ from: id, x: (e.clientX - r.left) / scale, y: (e.clientY - r.top) / scale, over: null });
64
+ };
65
+
66
+ const path = (e) => {
67
+ const a = byId[e.from], b = byId[e.to];
68
+ return a && b ? curve(outPt(a), inPt(b, e.toPort || 0)) : "";
69
+ };
70
+ const dragPath = () => {
71
+ const a = byId[drag.from];
72
+ if (!a) return "";
73
+ const end = drag.over && byId[drag.over.id] ? inPt(byId[drag.over.id], drag.over.port) : { x: drag.x, y: drag.y };
74
+ return curve(outPt(a), end);
75
+ };
76
+
77
+ return (
78
+ <div ref={ref} style={{ position: "relative", width, height, background: "var(--bg-app)", overflow: "hidden", cursor: drag ? "grabbing" : "default", ...style }}>
79
+ <svg style={{ position: "absolute", inset: 0, width: "100%", height: "100%", pointerEvents: "none", overflow: "visible" }}>
80
+ {edges.map((e, i) => <path key={i} d={path(e)} fill="none" stroke="var(--edge)" strokeWidth="1.5" />)}
81
+ {drag ? <path d={dragPath()} fill="none" stroke="var(--action-primary)" strokeWidth="1.5" strokeDasharray="5 4" /> : null}
82
+ </svg>
83
+ {nodes.map(({ id, x, y, ...props }) => (
84
+ <NodeCard key={id} {...props} selected={selectedId === id}
85
+ onClick={() => !drag && onSelect && onSelect(id)} onMenu={(e) => onMenu && onMenu(id, e)}
86
+ onOutputDown={onConnect ? (e) => start(id, e) : undefined}
87
+ onInputUp={onConnect ? () => {} : undefined}
88
+ outputTone={drag && drag.from === id ? "active" : "default"}
89
+ inputTones={drag && drag.over && drag.over.id === id ? Object.assign([], { [drag.over.port]: "target" }) : []}
90
+ style={{ position: "absolute", left: x, top: y }} />
91
+ ))}
92
+ </div>
93
+ );
94
+ }
@@ -0,0 +1,73 @@
1
+ <script setup>
2
+ import { computed, ref, onUnmounted } from 'vue'
3
+ import NodeCard from './NodeCard.vue'
4
+ /**
5
+ * Pipeline canvas: #fafafa surface, slate bezier edges, absolutely-placed NodeCards.
6
+ * nodes: [{id,x,y,...NodeCardProps}]; edges: [{from,to,toPort}] (toPort index for A/B inputs).
7
+ * With connectable, holding an output port drags a dashed wire; input ports light up as drop
8
+ * targets and the drop emits connect {from,to,toPort}. scale tells the canvas its zoom factor.
9
+ */
10
+ const props = defineProps({ nodes: { type: Array, default: () => [] }, edges: { type: Array, default: () => [] }, selectedId: [String, Number], connectable: Boolean, snapRadius: { type: Number, default: 30 }, scale: { type: Number, default: 1 }, width: { type: [String, Number], default: '100%' }, height: { type: [String, Number], default: '100%' }, style: Object })
11
+ const emit = defineEmits(['select', 'menu', 'connect'])
12
+ const NODE_W = 220
13
+ const root = ref(null)
14
+ const drag = ref(null)
15
+ const byId = computed(() => Object.fromEntries(props.nodes.map(n => [n.id, n])))
16
+ function outPt(n) { return { x: n.x + NODE_W, y: n.y + 44 } }
17
+ function inPt(n, portIdx = 0) { const multi = (n.inputs || []).filter(Boolean).length > 1; return { x: n.x, y: multi ? n.y + 23 + portIdx * 38 : n.y + 44 } }
18
+ function curve(p1, p2) { const dx = Math.max(40, (p2.x - p1.x) / 2); return `M ${p1.x} ${p1.y} C ${p1.x + dx} ${p1.y}, ${p2.x - dx} ${p2.y}, ${p2.x} ${p2.y}` }
19
+ function path(e) { const a = byId.value[e.from], b = byId.value[e.to]; return a && b ? curve(outPt(a), inPt(b, e.toPort || 0)) : '' }
20
+ const dragPath = computed(() => {
21
+ const d = drag.value; if (!d) return ''
22
+ const a = byId.value[d.from]; if (!a) return ''
23
+ const end = d.over && byId.value[d.over.id] ? inPt(byId.value[d.over.id], d.over.port) : { x: d.x, y: d.y }
24
+ return curve(outPt(a), end)
25
+ })
26
+ function at(e) { const r = root.value.getBoundingClientRect(); return { x: (e.clientX - r.left) / props.scale, y: (e.clientY - r.top) / props.scale } }
27
+ /* The drop target is hit-tested from the pointer position rather than port hover:
28
+ during a drag the cursor is often over the wire layer, not the 22px handle. */
29
+ function hitTest(x, y, fromId) {
30
+ let best = null
31
+ for (const n of props.nodes) {
32
+ if (n.id === fromId) continue
33
+ const ports = n.inputs || []
34
+ for (let i = 0; i < ports.length; i++) {
35
+ const p = inPt(n, i)
36
+ const d = Math.hypot(p.x - x, p.y - y)
37
+ if (d <= props.snapRadius && (!best || d < best.d)) best = { id: n.id, port: i, d }
38
+ }
39
+ }
40
+ return best ? { id: best.id, port: best.port } : null
41
+ }
42
+ function move(e) {
43
+ if (!drag.value) return
44
+ const p = at(e)
45
+ drag.value = { ...drag.value, ...p, over: hitTest(p.x, p.y, drag.value.from) }
46
+ }
47
+ function up() {
48
+ const d = drag.value
49
+ if (d && d.over) emit('connect', { from: d.from, to: d.over.id, toPort: d.over.port })
50
+ drag.value = null
51
+ window.removeEventListener('pointermove', move); window.removeEventListener('pointerup', up)
52
+ }
53
+ function start(id, e) {
54
+ if (!props.connectable) return
55
+ drag.value = { from: id, ...at(e), over: null }
56
+ window.addEventListener('pointermove', move); window.addEventListener('pointerup', up)
57
+ }
58
+ const inputTones = id => (drag.value && drag.value.over && drag.value.over.id === id ? Object.assign([], { [drag.value.over.port]: 'target' }) : [])
59
+ onUnmounted(() => { window.removeEventListener('pointermove', move); window.removeEventListener('pointerup', up) })
60
+ </script>
61
+ <template>
62
+ <div ref="root" :style="{ position: 'relative', width, height, background: 'var(--bg-app)', overflow: 'hidden', cursor: drag ? 'grabbing' : 'default', ...style }">
63
+ <svg style="position:absolute;inset:0;width:100%;height:100%;pointer-events:none;overflow:visible">
64
+ <path v-for="(e, i) in edges" :key="i" :d="path(e)" fill="none" stroke="var(--edge)" stroke-width="1.5" />
65
+ <path v-if="drag" :d="dragPath" fill="none" stroke="var(--action-primary)" stroke-width="1.5" stroke-dasharray="5 4" />
66
+ </svg>
67
+ <NodeCard v-for="n in nodes" :key="n.id" v-bind="n" :selected="selectedId === n.id" :live="connectable"
68
+ :output-tone="drag && drag.from === n.id ? 'active' : 'default'" :input-tones="inputTones(n.id)"
69
+ @click="!drag && emit('select', n.id)" @menu="emit('menu', n.id)"
70
+ @output-down="start(n.id, $event)"
71
+ :style="{ position: 'absolute', left: n.x + 'px', top: n.y + 'px' }" />
72
+ </div>
73
+ </template>
@@ -0,0 +1,9 @@
1
+ import * as React from "react";
2
+ /** Floating canvas zoom control. Addition — the pipeline canvas implies pan/zoom but the source frames never draw its control. */
3
+ export interface ZoomControlsProps {
4
+ value?: number;
5
+ onChange?: (next: number) => void;
6
+ onFit?: () => void;
7
+ style?: React.CSSProperties;
8
+ }
9
+ export declare function ZoomControls(props: ZoomControlsProps): JSX.Element;
@@ -0,0 +1,15 @@
1
+ import React from "react";
2
+ import { IconButton } from "../buttons/IconButton.jsx";
3
+
4
+ /** Floating canvas zoom control (− / percentage / + / fit-to-view). */
5
+ export function ZoomControls({ value = 100, onChange, onFit, style }) {
6
+ return (
7
+ <div style={{ display: "inline-flex", alignItems: "center", gap: 2, background: "var(--bg-surface)", border: "1px solid var(--border-control)", borderRadius: "var(--radius-md)", boxShadow: "var(--shadow-menu)", padding: 3, boxSizing: "border-box", ...style }}>
8
+ <IconButton icon="minus" size="sm" onClick={() => onChange && onChange(Math.max(25, value - 10))} label="Zoom out" />
9
+ <span style={{ minWidth: 40, textAlign: "center", fontFamily: "var(--font-sans)", fontSize: "var(--text-xs)", color: "var(--text-secondary)" }}>{value}%</span>
10
+ <IconButton icon="plus" size="sm" onClick={() => onChange && onChange(Math.min(200, value + 10))} label="Zoom in" />
11
+ <span style={{ width: 1, alignSelf: "stretch", background: "var(--border-subtle)", margin: "0 2px" }} />
12
+ <IconButton icon="target" size="sm" onClick={onFit} label="Fit to view" />
13
+ </div>
14
+ );
15
+ }
@@ -0,0 +1,15 @@
1
+ <script setup>
2
+ import IconButton from '../buttons/IconButton.vue'
3
+ // Floating canvas zoom control (− / percentage / + / fit-to-view).
4
+ const props = defineProps({ modelValue: { type: Number, default: 100 }, style: Object })
5
+ const emit = defineEmits(['update:modelValue', 'fit'])
6
+ </script>
7
+ <template>
8
+ <div :style="{ display: 'inline-flex', alignItems: 'center', gap: 2, background: 'var(--bg-surface)', border: '1px solid var(--border-control)', borderRadius: 'var(--radius-md)', boxShadow: 'var(--shadow-menu)', padding: 3, boxSizing: 'border-box', ...style }">
9
+ <IconButton icon="minus" size="sm" label="Zoom out" @click="emit('update:modelValue', Math.max(25, modelValue - 10))" />
10
+ <span style="min-width:40px;text-align:center;font-family:var(--font-sans);font-size:var(--text-xs);color:var(--text-secondary)">{{ modelValue }}%</span>
11
+ <IconButton icon="plus" size="sm" label="Zoom in" @click="emit('update:modelValue', Math.min(200, modelValue + 10))" />
12
+ <span style="width:1px;align-self:stretch;background:var(--border-subtle);margin:0 2px" />
13
+ <IconButton icon="target" size="sm" label="Fit to view" @click="emit('fit')" />
14
+ </div>
15
+ </template>
@@ -0,0 +1,13 @@
1
+ <!-- @dsCard group="Directory Index" viewport="700x110" name="Pipeline dir" subtitle="Full card: Components → Pipeline Editor" -->
2
+ <!DOCTYPE html>
3
+ <html><head><meta charset="utf-8"><link rel="stylesheet" href="../../styles.css">
4
+ <script src="https://unpkg.com/react@18.3.1/umd/react.development.js" integrity="sha384-hD6/rw4ppMLGNu3tX5cjIb+uRZ7UkRJ6BPkLpg4hAu/6onKUg4lLsHAs9EBPT82L" crossorigin="anonymous"></script>
5
+ <script src="https://unpkg.com/react-dom@18.3.1/umd/react-dom.development.js" integrity="sha384-u6aeetuaXnQ38mYT8rp6sbXaQe3NL9t+IBXmnYxwkUI2Hw4bsp2Wvmx4yRQF1uAm" crossorigin="anonymous"></script>
6
+ <script src="https://unpkg.com/@babel/standalone@7.29.0/babel.min.js" integrity="sha384-m08KidiNqLdpJqLq95G/LEi8Qvjl/xUYll3QILypMoQ65QorJ9Lvtp2RXYGBFj1y" crossorigin="anonymous"></script>
7
+ <script src="../../_ds_bundle.js"></script>
8
+ <style>body{margin:0;background:var(--bg-surface);padding:16px;font-family:var(--font-sans)}</style></head>
9
+ <body><div id="root"></div>
10
+ <script type="text/babel">
11
+ const { NodeCard } = window.KeybricksDesignSystem_71231a;
12
+ ReactDOM.createRoot(document.getElementById("root")).render(<NodeCard title="Sales Orders" subtitle="Detail Sheet" icon="table" hue="source"/>);
13
+ </script></body></html>
@@ -0,0 +1,22 @@
1
+ Pipeline editor parts, each with its own card: `NodeCard` (+`Port`/`PortLabel`), `PalettePanel` (+`PIPELINE_CATALOG`, `PaletteItem`, `PaletteListItem`), `PipelineCanvas`, `ConfigPanel`, `ZoomControls`. `DataPreview` is the bottom drawer that wraps the shared dense `DataTable` — reach for `DataTable` directly unless you need the drawer chrome (Debug Mode + collapse).
2
+
3
+ ```jsx
4
+ <PipelineCanvas selectedId={sel} onSelect={setSel}
5
+ nodes={[
6
+ {id:"a",x:90,y:90,title:"Sales Orders",subtitle:"Detail Sheet",icon:"table",hue:"source",inputs:[]},
7
+ {id:"j",x:420,y:150,title:"Sales × Product Join",subtitle:"Association Match",icon:"shuffle",hue:"join",badge:"error",inputs:["A","B"]},
8
+ ]}
9
+ edges={[{from:"a",to:"j",toPort:0}]}/>
10
+ <ConfigPanel title="Sales Orders" subtitle="Data Source · Detail Sheet">…Fields…</ConfigPanel>
11
+ <DataPreview columns={[{key:"id",label:"ID",mono:true}]} rows={[{id:"528563"}]}/>
12
+ ```
13
+
14
+ Hues follow PIPELINE_CATALOG: source/join/transform/merge/output. Node subtitles show the node type.
15
+
16
+ Ports carry three tones: grey at rest, `--action-primary` on hover and while dragging (`outputTone="active"`), and a crosshair drop target (`inputTones[i]="target"`). Pass `onConnect` to `PipelineCanvas` to enable wire dragging — it hit-tests the pointer against input-port geometry within `snapRadius` (30px) and reports `{from,to,toPort}`.
17
+
18
+ `ZoomControls` (addition) — the pipeline canvas implies pan/zoom but the source frames never draw its control:
19
+
20
+ ```jsx
21
+ <ZoomControls value={zoom} onChange={setZoom} onFit={()=>setZoom(100)}/>
22
+ ```
@@ -0,0 +1,11 @@
1
+ import * as React from "react";
2
+ /** Inset segmented control with a raised active segment. Addition — not in the source file. */
3
+ export interface SegmentedControlProps {
4
+ /** Plain labels, or {label, icon} entries */
5
+ options?: (string | { label: string; icon?: string })[];
6
+ value?: string;
7
+ onChange?: (value: string) => void;
8
+ size?: "sm" | "md";
9
+ style?: React.CSSProperties;
10
+ }
11
+ export declare function SegmentedControl(props: SegmentedControlProps): JSX.Element;
@@ -0,0 +1,21 @@
1
+ import React from "react";
2
+ import { Icon } from "../icons/Icon.jsx";
3
+
4
+ /** Segmented control — inset track, raised active segment. options: string[] or [{label,icon}]. */
5
+ export function SegmentedControl({ options = [], value, onChange, size = "md", style }) {
6
+ const h = size === "sm" ? 26 : 32;
7
+ return (
8
+ <div style={{ display: "inline-flex", padding: 2, gap: 2, background: "var(--bg-inset)", border: "1px solid var(--border-control)", borderRadius: "var(--radius-md)", boxSizing: "border-box", ...style }}>
9
+ {options.map((o) => {
10
+ const label = typeof o === "string" ? o : o.label;
11
+ const is = value === label;
12
+ return (
13
+ <button key={label} type="button" onClick={() => onChange && onChange(label)}
14
+ style={{ height: h - 6, padding: "0 10px", display: "inline-flex", alignItems: "center", gap: 6, borderRadius: "var(--radius-sm)", border: "none", cursor: "pointer", background: is ? "var(--bg-surface)" : "transparent", boxShadow: is ? "0 1px 2px rgba(0,0,0,.08)" : "none", fontFamily: "var(--font-sans)", fontWeight: "var(--weight-medium)", fontSize: size === "sm" ? "var(--text-xs)" : "var(--text-sm)", color: is ? "var(--text-heading)" : "var(--text-secondary)", whiteSpace: "nowrap", transition: "var(--t-hover)" }}>
15
+ {typeof o === "object" && o.icon ? <Icon name={o.icon} size={13} /> : null}{label}
16
+ </button>
17
+ );
18
+ })}
19
+ </div>
20
+ );
21
+ }
@@ -0,0 +1,15 @@
1
+ <script setup>
2
+ import Icon from '../icons/Icon.vue'
3
+ // Segmented control — inset track, raised active segment. options: string[] or [{label,icon}].
4
+ const props = defineProps({ options: { type: Array, default: () => [] }, modelValue: String, size: { type: String, default: 'md' }, style: Object })
5
+ const emit = defineEmits(['update:modelValue'])
6
+ function label(o) { return typeof o === 'string' ? o : o.label }
7
+ </script>
8
+ <template>
9
+ <div :style="{ display: 'inline-flex', padding: 2, gap: 2, background: 'var(--bg-inset)', border: '1px solid var(--border-control)', borderRadius: 'var(--radius-md)', boxSizing: 'border-box', ...style }">
10
+ <button v-for="o in options" :key="label(o)" type="button" @click="emit('update:modelValue', label(o))"
11
+ :style="{ height: (size === 'sm' ? 26 : 32) - 6, padding: '0 10px', display: 'inline-flex', alignItems: 'center', gap: 6, borderRadius: 'var(--radius-sm)', border: 'none', cursor: 'pointer', background: modelValue === label(o) ? 'var(--bg-surface)' : 'transparent', boxShadow: modelValue === label(o) ? '0 1px 2px rgba(0,0,0,.08)' : 'none', fontFamily: 'var(--font-sans)', fontWeight: 'var(--weight-medium)', fontSize: size === 'sm' ? 'var(--text-xs)' : 'var(--text-sm)', color: modelValue === label(o) ? 'var(--text-heading)' : 'var(--text-secondary)', whiteSpace: 'nowrap', transition: 'var(--t-hover)' }">
12
+ <Icon v-if="typeof o === 'object' && o.icon" :name="o.icon" :size="13" />{{ label(o) }}
13
+ </button>
14
+ </div>
15
+ </template>
@@ -0,0 +1,13 @@
1
+ import * as React from "react";
2
+ /** Underline tabs (Import/Export). Active: blue text + 2px blue underline on hairline baseline. */
3
+ export interface TabsProps {
4
+ tabs?: string[];
5
+ active?: string;
6
+ onChange?: (tab: string) => void;
7
+ style?: React.CSSProperties;
8
+ }
9
+ export declare function Tabs(props: TabsProps): JSX.Element;
10
+ /** 12px compact underline tabs for panels (Node Info / Calc Rules / ...). */
11
+ export declare function PanelTabs(props: TabsProps): JSX.Element;
12
+ /** Text pill filter tabs; active gets a #f5f5f5 pill. */
13
+ export declare function PillTabs(props: TabsProps): JSX.Element;