@keyfunc/keybricks-ds 1.0.3 → 2.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (358) hide show
  1. package/DEPLOY.md +4 -4
  2. package/DESIGN.md +154 -53
  3. package/INTEGRATION.md +176 -36
  4. package/SKILL.md +6 -4
  5. package/_adherence.oxlintrc.json +183 -72
  6. package/_scripts/build-index.mjs +9 -0
  7. package/_scripts/build-tokens.mjs +5 -2
  8. package/assets/icons/icon-index.js +1 -1
  9. package/assets/icons/icon-index.json +1 -1
  10. package/components/_cards/accordion.card.html +2 -2
  11. package/components/_cards/action-chip.card.html +8 -3
  12. package/components/_cards/activity.card.html +2 -2
  13. package/components/_cards/alert.card.html +2 -2
  14. package/components/_cards/app-chrome.card.html +4 -4
  15. package/components/_cards/banner.card.html +1 -1
  16. package/components/_cards/breadcrumb.card.html +2 -2
  17. package/components/_cards/button-1-base.card.html +2 -2
  18. package/components/_cards/button-2-states.card.html +14 -14
  19. package/components/_cards/button-3-sizes-icons.card.html +1 -1
  20. package/components/_cards/button-4-group.card.html +5 -5
  21. package/components/_cards/canvas-zoom-controls.card.html +1 -1
  22. package/components/_cards/cards-indicators.card.html +2 -2
  23. package/components/_cards/charts-1-sparkline.card.html +2 -2
  24. package/components/_cards/charts-10-gauge.card.html +4 -4
  25. package/components/_cards/charts-11-funnel.card.html +2 -2
  26. package/components/_cards/charts-12-treemap.card.html +2 -2
  27. package/components/_cards/charts-14-radar.card.html +1 -1
  28. package/components/_cards/charts-15-distribution.card.html +1 -1
  29. package/components/_cards/charts-16-pareto.card.html +2 -2
  30. package/components/_cards/charts-17-candlestick.card.html +2 -2
  31. package/components/_cards/charts-18-sankey.card.html +2 -2
  32. package/components/_cards/charts-19-chord.card.html +2 -2
  33. package/components/_cards/charts-2-line.card.html +2 -2
  34. package/components/_cards/charts-20-sunburst.card.html +2 -2
  35. package/components/_cards/charts-21-worldmap.card.html +2 -2
  36. package/components/_cards/charts-22-gantt.card.html +2 -2
  37. package/components/_cards/charts-23-bar3d.card.html +2 -2
  38. package/components/_cards/charts-24-pie3d.card.html +2 -2
  39. package/components/_cards/charts-25-surface3d.card.html +2 -2
  40. package/components/_cards/charts-26-scatter3d.card.html +2 -2
  41. package/components/_cards/charts-27-ribbon3d.card.html +2 -2
  42. package/components/_cards/charts-3-bar.card.html +2 -2
  43. package/components/_cards/charts-4-barlist.card.html +2 -2
  44. package/components/_cards/charts-5-donut.card.html +3 -3
  45. package/components/_cards/charts-6-scatter.card.html +2 -2
  46. package/components/_cards/charts-7-heatmap.card.html +2 -2
  47. package/components/_cards/charts-8-waterfall.card.html +2 -2
  48. package/components/_cards/charts-9-bullet.card.html +2 -2
  49. package/components/_cards/charts-99-fullpage.card.html +5 -5
  50. package/components/_cards/checkbox.card.html +4 -4
  51. package/components/_cards/codeblock.card.html +1 -1
  52. package/components/_cards/combobox.card.html +3 -2
  53. package/components/_cards/context-menu.card.html +3 -2
  54. package/components/_cards/date-picker.card.html +5 -2
  55. package/components/_cards/diffvalue.card.html +2 -2
  56. package/components/_cards/divider.card.html +3 -3
  57. package/components/_cards/drawer.card.html +2 -2
  58. package/components/_cards/dropdown-menu.card.html +6 -6
  59. package/components/_cards/dropzone.card.html +1 -1
  60. package/components/_cards/empty-state.card.html +5 -5
  61. package/components/_cards/filter-bar.card.html +5 -5
  62. package/components/_cards/icon-button.card.html +2 -2
  63. package/components/_cards/icons-1-core.card.html +2 -2
  64. package/components/_cards/icons-2-feather.card.html +3 -3
  65. package/components/_cards/icons-3-unicons.card.html +3 -3
  66. package/components/_cards/input.card.html +5 -2
  67. package/components/_cards/kbd.card.html +2 -2
  68. package/components/_cards/keyvalue.card.html +2 -2
  69. package/components/_cards/listrow.card.html +2 -2
  70. package/components/_cards/loading.card.html +2 -2
  71. package/components/_cards/log-viewer.card.html +2 -2
  72. package/components/_cards/modal.card.html +9 -9
  73. package/components/_cards/multi-select.card.html +3 -2
  74. package/components/_cards/number-stepper.card.html +3 -2
  75. package/components/_cards/pagination.card.html +3 -2
  76. package/components/_cards/people.card.html +3 -3
  77. package/components/_cards/pipeline-node.card.html +2 -2
  78. package/components/_cards/pipeline-palette.card.html +4 -4
  79. package/components/_cards/radio.card.html +46 -0
  80. package/components/_cards/search.card.html +5 -2
  81. package/components/_cards/segmented-control.card.html +39 -0
  82. package/components/_cards/select.card.html +4 -4
  83. package/components/_cards/slider.card.html +1 -1
  84. package/components/_cards/smart-table.card.html +1 -1
  85. package/components/_cards/spreadsheet.card.html +2 -2
  86. package/components/_cards/stepper.card.html +2 -2
  87. package/components/_cards/table.card.html +103 -0
  88. package/components/_cards/tabs.card.html +3 -2
  89. package/components/_cards/tag.card.html +5 -2
  90. package/components/_cards/textarea.card.html +2 -2
  91. package/components/_cards/timeline.card.html +1 -1
  92. package/components/_cards/toast.card.html +4 -4
  93. package/components/_cards/toggles.card.html +45 -56
  94. package/components/_cards/tooltip.card.html +5 -5
  95. package/components/_cards/tree.card.html +2 -2
  96. package/components/_shared/src-buttons.js +1 -1
  97. package/components/_shared/src-charts.js +1 -1
  98. package/components/_shared/src-data.js +1 -1
  99. package/components/_shared/src-display.js +1 -1
  100. package/components/_shared/src-feedback.js +1 -1
  101. package/components/_shared/src-forms.js +1 -1
  102. package/components/_shared/src-navigation.js +1 -1
  103. package/components/_shared/src-pipeline.js +1 -1
  104. package/components/_shared/src-tabs.js +1 -1
  105. package/components/_shared/view-source.js +9 -4
  106. package/components/_vue/index.mjs +9 -5
  107. package/components/buttons/ActionChip.d.ts +3 -1
  108. package/components/buttons/ActionChip.jsx +4 -4
  109. package/components/buttons/ActionChip.vue +4 -4
  110. package/components/buttons/Button.d.ts +5 -2
  111. package/components/buttons/Button.jsx +15 -18
  112. package/components/buttons/Button.vue +17 -18
  113. package/components/buttons/ButtonGroup.vue +1 -1
  114. package/components/buttons/IconButton.d.ts +2 -1
  115. package/components/buttons/IconButton.jsx +9 -7
  116. package/components/buttons/IconButton.vue +10 -8
  117. package/components/buttons/buttons.prompt.md +6 -5
  118. package/components/charts/Bar3D.jsx +2 -2
  119. package/components/charts/Bar3D.vue +2 -2
  120. package/components/charts/BarChart.jsx +4 -4
  121. package/components/charts/BarChart.vue +4 -4
  122. package/components/charts/BarList.jsx +1 -1
  123. package/components/charts/BarList.vue +1 -1
  124. package/components/charts/BoxPlot.jsx +1 -1
  125. package/components/charts/BoxPlot.vue +2 -2
  126. package/components/charts/BulletChart.jsx +1 -1
  127. package/components/charts/BulletChart.vue +1 -1
  128. package/components/charts/CandlestickChart.jsx +2 -2
  129. package/components/charts/CandlestickChart.vue +3 -3
  130. package/components/charts/ChartKit.jsx +5 -5
  131. package/components/charts/ChartLegend.vue +16 -0
  132. package/components/charts/ChartTooltip.vue +16 -0
  133. package/components/charts/ChordChart.jsx +2 -2
  134. package/components/charts/ChordChart.vue +2 -2
  135. package/components/charts/GanttChart.jsx +2 -2
  136. package/components/charts/GanttChart.vue +2 -2
  137. package/components/charts/GaugeChart.jsx +2 -2
  138. package/components/charts/GaugeChart.vue +2 -2
  139. package/components/charts/HeatmapChart.jsx +2 -2
  140. package/components/charts/HeatmapChart.vue +2 -2
  141. package/components/charts/Histogram.jsx +2 -2
  142. package/components/charts/Histogram.vue +3 -3
  143. package/components/charts/LineChart.jsx +1 -1
  144. package/components/charts/LineChart.vue +3 -3
  145. package/components/charts/ParetoChart.jsx +3 -3
  146. package/components/charts/ParetoChart.vue +4 -4
  147. package/components/charts/PlotGrid.vue +18 -0
  148. package/components/charts/RadarChart.jsx +1 -1
  149. package/components/charts/RadarChart.vue +1 -1
  150. package/components/charts/Ribbon3D.jsx +2 -2
  151. package/components/charts/Ribbon3D.vue +2 -2
  152. package/components/charts/SankeyChart.jsx +2 -2
  153. package/components/charts/SankeyChart.vue +2 -2
  154. package/components/charts/Scatter3D.jsx +1 -1
  155. package/components/charts/Scatter3D.vue +1 -1
  156. package/components/charts/ScatterChart.jsx +3 -3
  157. package/components/charts/ScatterChart.vue +4 -4
  158. package/components/charts/Sparkline.jsx +1 -1
  159. package/components/charts/Sparkline.vue +1 -1
  160. package/components/charts/SunburstChart.jsx +1 -1
  161. package/components/charts/SunburstChart.vue +1 -1
  162. package/components/charts/Surface3D.jsx +2 -2
  163. package/components/charts/Surface3D.vue +2 -2
  164. package/components/charts/TreemapChart.jsx +2 -2
  165. package/components/charts/TreemapChart.vue +2 -2
  166. package/components/charts/WaterfallChart.jsx +2 -2
  167. package/components/charts/WaterfallChart.vue +3 -3
  168. package/components/charts/WorldMap.jsx +2 -2
  169. package/components/charts/WorldMap.vue +2 -2
  170. package/components/charts/XLabels.vue +11 -0
  171. package/components/data/CodeBlock.jsx +1 -1
  172. package/components/data/CodeBlock.vue +1 -1
  173. package/components/data/DiffValue.jsx +1 -1
  174. package/components/data/DiffValue.vue +1 -1
  175. package/components/data/FilterBar.d.ts +2 -0
  176. package/components/data/FilterBar.jsx +10 -9
  177. package/components/data/FilterBar.vue +9 -8
  178. package/components/data/KeyValue.jsx +3 -3
  179. package/components/data/KeyValue.vue +3 -3
  180. package/components/data/ListRow.jsx +2 -2
  181. package/components/data/ListRow.vue +2 -2
  182. package/components/data/Pagination.d.ts +5 -1
  183. package/components/data/Pagination.jsx +16 -12
  184. package/components/data/Pagination.vue +14 -9
  185. package/components/data/SmartTable.d.ts +4 -1
  186. package/components/data/SmartTable.jsx +16 -14
  187. package/components/data/SmartTable.vue +25 -22
  188. package/components/data/Spreadsheet.d.ts +2 -0
  189. package/components/data/Spreadsheet.jsx +12 -11
  190. package/components/data/Spreadsheet.vue +14 -13
  191. package/components/data/Table.d.ts +47 -0
  192. package/components/data/Table.jsx +85 -0
  193. package/components/data/Table.vue +63 -0
  194. package/components/data/data.prompt.md +3 -3
  195. package/components/display/Avatar.vue +3 -2
  196. package/components/display/AvatarGroup.vue +3 -2
  197. package/components/display/Badge.vue +1 -1
  198. package/components/display/Divider.vue +3 -3
  199. package/components/display/Donut.vue +3 -2
  200. package/components/display/IconTile.vue +2 -1
  201. package/components/display/Kbd.vue +1 -1
  202. package/components/display/ProgressBar.jsx +1 -1
  203. package/components/display/ProgressBar.vue +1 -1
  204. package/components/display/StatCard.vue +1 -1
  205. package/components/display/Tag.d.ts +3 -1
  206. package/components/display/Tag.jsx +4 -4
  207. package/components/display/Tag.vue +4 -4
  208. package/components/feedback/Accordion.jsx +2 -2
  209. package/components/feedback/Accordion.vue +2 -2
  210. package/components/feedback/ActivityItem.d.ts +3 -1
  211. package/components/feedback/ActivityItem.jsx +5 -5
  212. package/components/feedback/ActivityItem.vue +5 -4
  213. package/components/feedback/Alert.jsx +4 -4
  214. package/components/feedback/Alert.vue +3 -3
  215. package/components/feedback/Banner.jsx +5 -5
  216. package/components/feedback/Banner.vue +5 -5
  217. package/components/feedback/ContextMenu.d.ts +3 -1
  218. package/components/feedback/ContextMenu.jsx +5 -5
  219. package/components/feedback/ContextMenu.vue +5 -5
  220. package/components/feedback/DotActivity.vue +3 -3
  221. package/components/feedback/Drawer.d.ts +2 -0
  222. package/components/feedback/Drawer.jsx +6 -6
  223. package/components/feedback/Drawer.vue +22 -15
  224. package/components/feedback/EmptyState.vue +2 -2
  225. package/components/feedback/LogViewer.vue +1 -1
  226. package/components/feedback/Modal.d.ts +2 -0
  227. package/components/feedback/Modal.jsx +12 -11
  228. package/components/feedback/Modal.vue +10 -8
  229. package/components/feedback/Skeleton.vue +2 -1
  230. package/components/feedback/Spinner.vue +2 -1
  231. package/components/feedback/Stepper.vue +1 -1
  232. package/components/feedback/Timeline.jsx +1 -1
  233. package/components/feedback/Timeline.vue +1 -1
  234. package/components/feedback/Toast.vue +4 -4
  235. package/components/feedback/ToastStack.vue +11 -0
  236. package/components/feedback/Tooltip.vue +19 -0
  237. package/components/feedback/feedback.prompt.md +4 -4
  238. package/components/forms/Checkbox.d.ts +3 -2
  239. package/components/forms/Checkbox.jsx +7 -7
  240. package/components/forms/Checkbox.vue +8 -8
  241. package/components/forms/Combobox.d.ts +2 -0
  242. package/components/forms/Combobox.jsx +12 -10
  243. package/components/forms/Combobox.vue +11 -10
  244. package/components/forms/DatePicker.d.ts +4 -0
  245. package/components/forms/DatePicker.jsx +16 -12
  246. package/components/forms/DatePicker.vue +15 -11
  247. package/components/forms/Dropzone.jsx +2 -2
  248. package/components/forms/Dropzone.vue +5 -5
  249. package/components/forms/Field.d.ts +5 -1
  250. package/components/forms/Field.jsx +4 -4
  251. package/components/forms/Field.vue +4 -4
  252. package/components/forms/Input.d.ts +5 -1
  253. package/components/forms/Input.jsx +7 -7
  254. package/components/forms/Input.vue +3 -3
  255. package/components/forms/MultiSelect.d.ts +2 -0
  256. package/components/forms/MultiSelect.jsx +13 -11
  257. package/components/forms/MultiSelect.vue +12 -11
  258. package/components/forms/NumberStepper.d.ts +3 -1
  259. package/components/forms/NumberStepper.jsx +7 -7
  260. package/components/forms/NumberStepper.vue +8 -7
  261. package/components/forms/Radio.d.ts +30 -0
  262. package/components/forms/Radio.jsx +65 -0
  263. package/components/forms/Radio.vue +17 -9
  264. package/components/forms/RadioGroup.vue +22 -4
  265. package/components/forms/SearchInput.d.ts +3 -1
  266. package/components/forms/SearchInput.jsx +6 -6
  267. package/components/forms/SearchInput.vue +7 -6
  268. package/components/forms/Select.d.ts +3 -2
  269. package/components/forms/Select.jsx +6 -7
  270. package/components/forms/Select.vue +6 -6
  271. package/components/forms/Slider.jsx +3 -3
  272. package/components/forms/Slider.vue +3 -3
  273. package/components/forms/Switch.d.ts +32 -24
  274. package/components/forms/Switch.jsx +85 -35
  275. package/components/forms/Switch.vue +57 -11
  276. package/components/forms/Textarea.vue +4 -4
  277. package/components/forms/forms.prompt.md +4 -1
  278. package/components/forms/input-base.js +2 -1
  279. package/components/index.d.ts +2 -2
  280. package/components/index.js +5 -5
  281. package/components/navigation/Breadcrumb.jsx +3 -3
  282. package/components/navigation/Breadcrumb.vue +4 -4
  283. package/components/navigation/DocTree.jsx +3 -3
  284. package/components/navigation/DocTree.vue +3 -3
  285. package/components/navigation/PageHeading.vue +1 -1
  286. package/components/navigation/PageToolbar.vue +7 -6
  287. package/components/navigation/Sidebar.jsx +1 -1
  288. package/components/navigation/Sidebar.vue +3 -3
  289. package/components/navigation/ThemeToggle.vue +2 -1
  290. package/components/navigation/TopBar.d.ts +3 -1
  291. package/components/navigation/TopBar.jsx +6 -6
  292. package/components/navigation/Tree.jsx +5 -5
  293. package/components/navigation/Tree.vue +5 -5
  294. package/components/pipeline/ConfigPanel.d.ts +2 -0
  295. package/components/pipeline/ConfigPanel.jsx +9 -9
  296. package/components/pipeline/ConfigPanel.vue +9 -9
  297. package/components/pipeline/DataPreview.d.ts +3 -1
  298. package/components/pipeline/DataPreview.jsx +7 -7
  299. package/components/pipeline/DataPreview.vue +7 -7
  300. package/components/pipeline/NodeCard.jsx +3 -3
  301. package/components/pipeline/NodeCard.vue +3 -3
  302. package/components/pipeline/PaletteItem.vue +2 -2
  303. package/components/pipeline/PaletteListItem.vue +1 -1
  304. package/components/pipeline/PalettePanel.jsx +2 -2
  305. package/components/pipeline/PalettePanel.vue +1 -1
  306. package/components/pipeline/Port.vue +15 -0
  307. package/components/pipeline/PortLabel.vue +15 -0
  308. package/components/pipeline/ZoomControls.vue +1 -1
  309. package/components/pipeline/port-skin.js +13 -0
  310. package/components/px.js +4 -0
  311. package/components/tabs/PanelTabs.vue +5 -4
  312. package/components/tabs/PillTabs.vue +5 -4
  313. package/components/tabs/SegmentedControl.d.ts +11 -4
  314. package/components/tabs/SegmentedControl.jsx +25 -10
  315. package/components/tabs/SegmentedControl.vue +19 -7
  316. package/components/tabs/Tabs.d.ts +5 -3
  317. package/components/tabs/Tabs.jsx +15 -15
  318. package/components/tabs/Tabs.vue +5 -5
  319. package/components/tabs/ViewToggle.d.ts +3 -1
  320. package/components/tabs/ViewToggle.jsx +5 -5
  321. package/components/tabs/ViewToggle.vue +5 -5
  322. package/components/tabs/tabs.prompt.md +4 -2
  323. package/keybricks.css +4 -0
  324. package/package.json +6 -3
  325. package/readme.md +90 -123
  326. package/readme.zh-CN.md +120 -0
  327. package/tokens/charts.css +20 -17
  328. package/tokens/colors.css +2 -2
  329. package/tokens/dark.css +2 -2
  330. package/tokens/hover.css +32 -0
  331. package/tokens/interaction.css +3 -1
  332. package/tokens/layout.css +29 -7
  333. package/tokens/tokens.d.ts +36 -0
  334. package/tokens/tokens.js +143 -89
  335. package/tokens/tokens.json +240 -106
  336. package/tokens/typography.css +27 -14
  337. package/components/_cards/brand-visual.card.html +0 -43
  338. package/components/_cards/datatable.card.html +0 -48
  339. package/components/_shared/src-brand.js +0 -1
  340. package/components/brand/BrandVisual.d.ts +0 -17
  341. package/components/brand/BrandVisual.jsx +0 -29
  342. package/components/brand/BrandVisual.vue +0 -34
  343. package/components/brand/_dir.card.html +0 -13
  344. package/components/brand/brandMotifs.js +0 -210
  345. package/components/buttons/_dir.card.html +0 -13
  346. package/components/charts/ChartKit.vue +0 -47
  347. package/components/charts/_dir.card.html +0 -7
  348. package/components/data/DataTable.d.ts +0 -28
  349. package/components/data/DataTable.jsx +0 -32
  350. package/components/data/DataTable.vue +0 -25
  351. package/components/data/_dir.card.html +0 -13
  352. package/components/display/_dir.card.html +0 -13
  353. package/components/feedback/_dir.card.html +0 -13
  354. package/components/forms/_dir.card.html +0 -13
  355. package/components/icons/_dir.card.html +0 -13
  356. package/components/navigation/_dir.card.html +0 -13
  357. package/components/pipeline/_dir.card.html +0 -13
  358. package/components/tabs/_dir.card.html +0 -13
@@ -1 +1 @@
1
- window.__KB_SRC__=Object.assign(window.__KB_SRC__||{},{"buttons/ActionChip.jsx":"import React from \"react\";\n\nconst chipTones = {\n success: { background: \"var(--success-bg)\", color: \"var(--success-text)\" },\n warning: { background: \"var(--warning-bg)\", color: \"var(--warning-text)\" },\n neutral: { background: \"var(--bg-hover)\", color: \"var(--text-body)\" },\n info: { background: \"var(--info-bg)\", color: \"var(--action-primary)\" },\n danger: { background: \"var(--danger-bg)\", color: \"var(--danger-text)\" },\n};\n\n/** Tinted bulk-action chip (\"Mark as New\", \"Mark as Overwrite\", \"Skip Selected\"). */\nexport function ActionChip({ tone = \"neutral\", children, onClick, style }) {\n const [hover, setHover] = React.useState(false);\n return (\n <button type=\"button\" onClick={onClick} onMouseEnter={() => setHover(true)} onMouseLeave={() => setHover(false)}\n style={{ height: 30, padding: \"0 12px\", borderRadius: \"var(--radius-md)\", border: \"none\", cursor: \"pointer\", fontFamily: \"var(--font-sans)\", fontWeight: \"var(--weight-medium)\", fontSize: \"var(--text-sm)\", lineHeight: \"var(--leading-sm)\", display: \"inline-flex\", alignItems: \"center\", filter: hover ? \"brightness(1.06) saturate(1.05)\" : \"none\", transition: \"var(--t-hover),filter var(--dur-fast) var(--ease-out)\", ...chipTones[tone], ...style }}>\n {children}\n </button>\n );\n}\n","buttons/ActionChip.vue":"<script setup>\nimport { ref, computed } from 'vue'\nconst chipTones = {\n success: { background: 'var(--success-bg)', color: 'var(--success-text)' },\n warning: { background: 'var(--warning-bg)', color: 'var(--warning-text)' },\n neutral: { background: 'var(--bg-hover)', color: 'var(--text-body)' },\n info: { background: 'var(--info-bg)', color: 'var(--action-primary)' },\n danger: { background: 'var(--danger-bg)', color: 'var(--danger-text)' },\n}\n// Tinted bulk-action chip (\"Mark as New\", \"Mark as Overwrite\", \"Skip Selected\").\nconst props = defineProps({ tone: { type: String, default: 'neutral' }, style: Object })\ndefineEmits(['click'])\nconst hover = ref(false)\nconst s = computed(() => ({ height: 30, padding: '0 12px', borderRadius: 'var(--radius-md)', border: 'none', cursor: 'pointer', fontFamily: 'var(--font-sans)', fontWeight: 'var(--weight-medium)', fontSize: 'var(--text-sm)', lineHeight: 'var(--leading-sm)', display: 'inline-flex', alignItems: 'center', filter: hover.value ? 'brightness(1.06) saturate(1.05)' : 'none', transition: 'var(--t-hover),filter var(--dur-fast) var(--ease-out)', ...chipTones[props.tone], ...props.style }))\n</script>\n<template>\n <button type=\"button\" @click=\"$emit('click')\" @mouseenter=\"hover = true\" @mouseleave=\"hover = false\" :style=\"s\"><slot /></button>\n</template>\n","buttons/Button.jsx":"import React from \"react\";\nimport { Icon } from \"../icons/Icon.jsx\";\n\nconst btnBase = { display: \"inline-flex\", alignItems: \"center\", justifyContent: \"center\", gap: 6, fontFamily: \"var(--font-sans)\", fontWeight: \"var(--weight-regular)\", fontSize: \"var(--text-base)\", lineHeight: \"var(--leading-base)\", letterSpacing: \"var(--tracking-base)\", border: \"1px solid transparent\", cursor: \"pointer\", whiteSpace: \"nowrap\", boxSizing: \"border-box\", background: \"transparent\", transition: \"var(--t-hover)\" };\n\nconst variants = {\n primary: { background: \"var(--action-primary)\", color: \"var(--on-accent)\" },\n dark: { background: \"var(--action-dark)\", color: \"var(--action-dark-fg)\" },\n outline: { background: \"var(--bg-surface)\", color: \"var(--text-body)\", borderColor: \"var(--border-control)\" },\n ghost: { color: \"var(--text-body)\" },\n \"primary-soft\": { background: \"var(--soft-bg)\", color: \"var(--action-primary)\", borderColor: \"var(--soft-border)\" },\n danger: { background: \"var(--danger)\", color: \"var(--on-accent)\" },\n \"danger-soft\": { background: \"var(--danger-bg)\", color: \"var(--danger-text)\" },\n text: { color: \"var(--text-secondary)\", padding: \"0\", height: \"auto\" },\n};\nconst hovers = {\n primary: \"var(--action-primary-hover)\", dark: \"var(--action-dark-hover)\",\n outline: \"var(--bg-hover)\", ghost: \"var(--bg-hover)\", \"primary-soft\": \"var(--soft-hover)\",\n danger: \"var(--danger-text)\", \"danger-soft\": \"var(--danger-bg)\",\n};\n/** Press (mouse-down) fills — one step past hover. */\nconst presses = {\n primary: \"var(--action-primary-active)\", dark: \"var(--action-dark-active)\",\n outline: \"var(--bg-press)\", ghost: \"var(--bg-press)\", \"primary-soft\": \"var(--soft-active)\",\n danger: \"var(--danger-active)\", \"danger-soft\": \"var(--danger-soft-active)\",\n};\n/** Variants that change text color (+ underline) on hover instead of a background wash. */\nconst colorHoverVariants = { text: \"var(--text-heading)\" };\nconst sizes = {\n sm: { height: 30, padding: \"6px 12px\", fontSize: \"var(--text-sm)\", lineHeight: \"var(--leading-sm)\", letterSpacing: 0, borderRadius: \"var(--radius-md)\" },\n md: { height: 32, padding: \"6px 12px\", borderRadius: \"var(--radius-md)\" },\n lg: { height: 35.5, padding: \"8px 16px\", fontWeight: \"var(--weight-medium)\", borderRadius: \"var(--radius-lg)\" },\n};\nconst iconOnlyPad = { sm: 0, md: 0, lg: 0 };\nconst iconOnlyBox = { sm: 30, md: 32, lg: 36 };\n\nfunction Spinner({ size, color }) {\n return <span style={{ display: \"inline-block\", width: size, height: size, borderRadius: \"var(--radius-full)\", border: \"2px solid currentColor\", borderTopColor: \"transparent\", opacity: .9, color, animation: \"kb-spin .7s linear infinite\", flexShrink: 0 }} />;\n}\n\n/** Keybricks button. variant: primary | dark | outline | ghost | primary-soft | danger | danger-soft | text; size: sm | md | lg. Interaction states: hover (one step darker) · press (two steps, set via mouse-down) · keyboard focus ring · loading · disabled. */\nexport function Button({ variant = \"primary\", size = \"md\", icon, iconSize, iconPosition = \"left\", medium, disabled, loading, fullWidth, iconOnly, label, pressed, focused, children, style, onClick, ...rest }) {\n const [hover, setHover] = React.useState(false);\n const [press, setPress] = React.useState(false);\n const [focus, setFocus] = React.useState(false);\n const busy = disabled || loading;\n const isPressed = press || pressed;\n const isFocused = focus || focused;\n const s = {\n ...btnBase, ...sizes[size], ...variants[variant],\n ...(medium ? { fontWeight: \"var(--weight-medium)\" } : null),\n ...(fullWidth ? { width: \"100%\" } : null),\n ...(iconOnly ? { width: iconOnlyBox[size], padding: iconOnlyPad[size], gap: 0 } : null),\n ...(busy ? { opacity: .55, cursor: \"default\" } : null),\n ...style,\n };\n if (!busy) {\n if (colorHoverVariants[variant]) {\n if (hover || isPressed) { s.color = colorHoverVariants[variant]; s.textDecoration = \"underline\"; }\n if (isPressed) s.opacity = .7;\n } else if (isPressed) {\n s.background = presses[variant];\n } else if (hover) {\n s.background = hovers[variant];\n }\n if (isFocused) s.boxShadow = \"var(--ring-focus)\";\n }\n const iSize = iconSize || (size === \"sm\" ? 12 : 14);\n const leading = loading ? <Spinner size={iSize} color={s.color} /> : (icon && iconPosition === \"left\" ? <Icon name={icon} size={iSize} /> : null);\n const trailing = !loading && icon && iconPosition === \"right\" ? <Icon name={icon} size={iSize} /> : null;\n return (\n <button type=\"button\" data-press=\"own\" style={s} disabled={busy} aria-label={iconOnly ? label : undefined} onClick={onClick}\n onMouseEnter={() => setHover(true)} onMouseLeave={() => { setHover(false); setPress(false); }}\n onMouseDown={() => setPress(true)} onMouseUp={() => setPress(false)}\n onKeyDown={(e) => { if (e.key === \" \" || e.key === \"Enter\") setPress(true); }} onKeyUp={() => setPress(false)}\n onFocus={(e) => { try { setFocus(e.target.matches(\":focus-visible\")); } catch (err) { setFocus(true); } }} onBlur={() => setFocus(false)} {...rest}>\n {leading}\n {iconOnly ? null : children}\n {trailing}\n </button>\n );\n}\n\n/** Attached row of Buttons sharing one outline (segmented action group). Children should be <Button variant=\"outline\"> or similar. */\nexport function ButtonGroup({ children, style }) {\n const items = React.Children.toArray(children);\n return (\n <div style={{ display: \"inline-flex\", ...style }}>\n {items.map((child, i) => React.cloneElement(child, {\n key: i,\n style: {\n ...(child.props.style || {}),\n borderRadius: 0,\n ...(i === 0 ? { borderTopLeftRadius: \"var(--radius-md)\", borderBottomLeftRadius: \"var(--radius-md)\" } : null),\n ...(i === items.length - 1 ? { borderTopRightRadius: \"var(--radius-md)\", borderBottomRightRadius: \"var(--radius-md)\" } : null),\n marginLeft: i === 0 ? 0 : -1,\n },\n }))}\n </div>\n );\n}\n","buttons/Button.vue":"<script setup>\nimport { computed, ref } from 'vue'\nimport Icon from '../icons/Icon.vue'\n\nconst btnBase = { display: 'inline-flex', alignItems: 'center', justifyContent: 'center', gap: 6, fontFamily: 'var(--font-sans)', fontWeight: 'var(--weight-regular)', fontSize: 'var(--text-base)', lineHeight: 'var(--leading-base)', letterSpacing: 'var(--tracking-base)', border: '1px solid transparent', cursor: 'pointer', whiteSpace: 'nowrap', boxSizing: 'border-box', background: 'transparent', transition: 'var(--t-hover)' }\nconst variants = {\n primary: { background: 'var(--action-primary)', color: 'var(--on-accent)' },\n dark: { background: 'var(--action-dark)', color: 'var(--action-dark-fg)' },\n outline: { background: 'var(--bg-surface)', color: 'var(--text-body)', borderColor: 'var(--border-control)' },\n ghost: { color: 'var(--text-body)' },\n 'primary-soft': { background: 'var(--soft-bg)', color: 'var(--action-primary)', borderColor: 'var(--soft-border)' },\n danger: { background: 'var(--danger)', color: 'var(--on-accent)' },\n 'danger-soft': { background: 'var(--danger-bg)', color: 'var(--danger-text)' },\n text: { color: 'var(--text-secondary)', padding: '0', height: 'auto' },\n}\nconst hovers = { primary: 'var(--action-primary-hover)', dark: 'var(--action-dark-hover)', outline: 'var(--bg-hover)', ghost: 'var(--bg-hover)', 'primary-soft': 'var(--soft-hover)', danger: 'var(--danger-text)', 'danger-soft': 'var(--danger-bg)' }\nconst presses = { primary: 'var(--action-primary-active)', dark: 'var(--action-dark-active)', outline: 'var(--bg-press)', ghost: 'var(--bg-press)', 'primary-soft': 'var(--soft-active)', danger: 'var(--danger-active)', 'danger-soft': 'var(--danger-soft-active)' }\nconst colorHoverVariants = { text: 'var(--text-heading)' }\nconst sizes = {\n sm: { height: 30, padding: '6px 12px', fontSize: 'var(--text-sm)', lineHeight: 'var(--leading-sm)', letterSpacing: 0, borderRadius: 'var(--radius-md)' },\n md: { height: 32, padding: '6px 12px', borderRadius: 'var(--radius-md)' },\n lg: { height: 35.5, padding: '8px 16px', fontWeight: 'var(--weight-medium)', borderRadius: 'var(--radius-lg)' },\n}\nconst iconOnlyPad = { sm: 0, md: 0, lg: 0 }\nconst iconOnlyBox = { sm: 30, md: 32, lg: 36 }\n\n// Button — variant: primary | dark | outline | ghost | primary-soft | danger | danger-soft | text; size: sm | md | lg.\nconst props = defineProps({\n variant: { type: String, default: 'primary' }, size: { type: String, default: 'md' },\n icon: String, iconSize: Number, iconPosition: { type: String, default: 'left' },\n medium: Boolean, disabled: Boolean, loading: Boolean, fullWidth: Boolean, iconOnly: Boolean,\n label: String, pressed: Boolean, focused: Boolean, style: Object,\n})\ndefineEmits(['click'])\nconst hover = ref(false), press = ref(false), focus = ref(false)\nconst busy = computed(() => props.disabled || props.loading)\nconst isPressed = computed(() => press.value || props.pressed)\nconst isFocused = computed(() => focus.value || props.focused)\nconst s = computed(() => {\n const base = { ...btnBase, ...sizes[props.size], ...variants[props.variant],\n ...(props.medium ? { fontWeight: 'var(--weight-medium)' } : null),\n ...(props.fullWidth ? { width: '100%' } : null),\n ...(props.iconOnly ? { width: iconOnlyBox[props.size], padding: iconOnlyPad[props.size], gap: 0 } : null),\n ...(busy.value ? { opacity: .55, cursor: 'default' } : null), ...props.style }\n if (!busy.value) {\n if (colorHoverVariants[props.variant]) {\n if (hover.value || isPressed.value) { base.color = colorHoverVariants[props.variant]; base.textDecoration = 'underline' }\n if (isPressed.value) base.opacity = .7\n } else if (isPressed.value) base.background = presses[props.variant]\n else if (hover.value) base.background = hovers[props.variant]\n if (isFocused.value) base.boxShadow = 'var(--ring-focus)'\n }\n return base\n})\nconst iSize = computed(() => props.iconSize || (props.size === 'sm' ? 12 : 14))\n</script>\n<template>\n <button type=\"button\" data-press=\"own\" :style=\"s\" :disabled=\"busy\" :aria-label=\"iconOnly ? label : undefined\"\n @click=\"$emit('click')\" @mouseenter=\"hover = true\" @mouseleave=\"hover = false; press = false\"\n @mousedown=\"press = true\" @mouseup=\"press = false\" @keydown.enter=\"press = true\" @keydown.space=\"press = true\" @keyup=\"press = false\"\n @focus=\"focus = $event.target.matches(':focus-visible')\" @blur=\"focus = false\">\n <span v-if=\"loading\" :style=\"{ display: 'inline-block', width: iSize, height: iSize, borderRadius: 'var(--radius-full)', border: '2px solid currentColor', borderTopColor: 'transparent', opacity: .9, animation: 'kb-spin .7s linear infinite', flexShrink: 0 }\" />\n <Icon v-else-if=\"icon && iconPosition === 'left'\" :name=\"icon\" :size=\"iSize\" />\n <slot v-if=\"!iconOnly\" />\n <Icon v-if=\"!loading && icon && iconPosition === 'right'\" :name=\"icon\" :size=\"iSize\" />\n </button>\n</template>\n","buttons/IconButton.jsx":"import React from \"react\";\nimport { Icon } from \"../icons/Icon.jsx\";\n\nconst ibSizes = { xs: { box: 22, icon: 14, radius: \"var(--radius-md)\" }, sm: { box: 26, icon: 14, radius: \"var(--radius-sm)\" }, md: { box: 28, icon: 16, radius: \"var(--radius-md)\" }, lg: { box: 34, icon: 18, radius: \"var(--radius-md)\" } };\n\n/** Square ghost icon button (toolbar/back/bell/view toggles). size: xs 22 | sm 26 | md 28 | lg 34. danger tints red; loading shows a spinner and disables interaction. States: hover · press · keyboard focus ring · active (persistent toggle-on) · disabled. */\nexport function IconButton({ icon, size = \"md\", active, muted, danger, disabled, loading, label, pressed, focused, style, onClick, ...rest }) {\n const [hover, setHover] = React.useState(false);\n const [press, setPress] = React.useState(false);\n const [focus, setFocus] = React.useState(false);\n const t = ibSizes[size];\n const busy = disabled || loading;\n const isPressed = (press || pressed) && !busy;\n const color = danger ? \"var(--danger)\" : muted ? \"var(--text-muted)\" : \"var(--text-body)\";\n const bg = isPressed ? (danger ? \"var(--danger-soft-active)\" : \"var(--bg-press)\")\n : active ? \"var(--bg-active)\"\n : hover && !busy ? (danger ? \"var(--danger-bg)\" : \"var(--bg-hover)\") : \"transparent\";\n return (\n <button type=\"button\" data-press=\"own\" aria-label={label} disabled={busy} onClick={onClick}\n onMouseEnter={() => setHover(true)} onMouseLeave={() => { setHover(false); setPress(false); }}\n onMouseDown={() => setPress(true)} onMouseUp={() => setPress(false)}\n onKeyDown={(e) => { if (e.key === \" \" || e.key === \"Enter\") setPress(true); }} onKeyUp={() => setPress(false)}\n onFocus={(e) => { try { setFocus(e.target.matches(\":focus-visible\")); } catch (err) { setFocus(true); } }} onBlur={() => setFocus(false)}\n style={{ width: t.box, height: t.box, borderRadius: t.radius, border: \"none\", cursor: busy ? \"default\" : \"pointer\", display: \"inline-flex\", alignItems: \"center\", justifyContent: \"center\", background: bg, color, opacity: busy ? .5 : 1, boxShadow: (focus || focused) && !busy ? \"var(--ring-focus)\" : \"none\", transition: \"var(--t-hover)\", padding: 0, flexShrink: 0, ...style }} {...rest}>\n {loading ? <span style={{ display: \"inline-block\", width: t.icon, height: t.icon, borderRadius: \"var(--radius-full)\", border: \"2px solid currentColor\", borderTopColor: \"transparent\", animation: \"kb-spin .7s linear infinite\" }} /> : <Icon name={icon} size={t.icon} />}\n </button>\n );\n}\n","buttons/IconButton.vue":"<script setup>\nimport { ref, computed } from 'vue'\nimport Icon from '../icons/Icon.vue'\nconst ibSizes = { xs: { box: 22, icon: 14, radius: 'var(--radius-md)' }, sm: { box: 26, icon: 14, radius: 'var(--radius-sm)' }, md: { box: 28, icon: 16, radius: 'var(--radius-md)' }, lg: { box: 34, icon: 18, radius: 'var(--radius-md)' } }\n// Square ghost icon button (toolbar/back/bell/view toggles). size: xs 22 | sm 26 | md 28 | lg 34.\nconst props = defineProps({ icon: String, size: { type: String, default: 'md' }, active: Boolean, muted: Boolean, danger: Boolean, disabled: Boolean, loading: Boolean, label: String, pressed: Boolean, focused: Boolean, style: Object })\ndefineEmits(['click'])\nconst hover = ref(false), press = ref(false), focus = ref(false)\nconst t = computed(() => ibSizes[props.size])\nconst busy = computed(() => props.disabled || props.loading)\nconst isPressed = computed(() => (press.value || props.pressed) && !busy.value)\nconst color = computed(() => props.danger ? 'var(--danger)' : props.muted ? 'var(--text-muted)' : 'var(--text-body)')\nconst bg = computed(() => isPressed.value ? (props.danger ? 'var(--danger-soft-active)' : 'var(--bg-press)') : props.active ? 'var(--bg-active)' : (hover.value && !busy.value ? (props.danger ? 'var(--danger-bg)' : 'var(--bg-hover)') : 'transparent'))\nconst s = computed(() => ({ width: t.value.box, height: t.value.box, borderRadius: t.value.radius, border: 'none', cursor: busy.value ? 'default' : 'pointer', display: 'inline-flex', alignItems: 'center', justifyContent: 'center', background: bg.value, color: color.value, opacity: busy.value ? .5 : 1, boxShadow: (focus.value || props.focused) && !busy.value ? 'var(--ring-focus)' : 'none', transition: 'var(--t-hover)', padding: 0, flexShrink: 0, ...props.style }))\n</script>\n<template>\n <button type=\"button\" data-press=\"own\" :aria-label=\"label\" :disabled=\"busy\" @click=\"$emit('click')\" @mouseenter=\"hover = true\" @mouseleave=\"hover = false; press = false\" @mousedown=\"press = true\" @mouseup=\"press = false\" @keydown.enter=\"press = true\" @keydown.space=\"press = true\" @keyup=\"press = false\" @focus=\"focus = $event.target.matches(':focus-visible')\" @blur=\"focus = false\" :style=\"s\">\n <span v-if=\"loading\" :style=\"{ display: 'inline-block', width: t.icon, height: t.icon, borderRadius: 'var(--radius-full)', border: '2px solid currentColor', borderTopColor: 'transparent', animation: 'kb-spin .7s linear infinite' }\" />\n <Icon v-else :name=\"icon\" :size=\"t.icon\" />\n </button>\n</template>\n","buttons/ButtonGroup.vue":"<script setup>\nimport { useSlots, computed } from 'vue'\nconst props = defineProps({ style: Object })\nconst slots = useSlots()\nconst items = computed(() => slots.default ? slots.default() : [])\n</script>\n<template>\n <div :style=\"{ display: 'inline-flex', ...style }\">\n <template v-for=\"(child, i) in items\" :key=\"i\">\n <component :is=\"child\" :style=\"{ borderRadius: 0,\n ...(i === 0 ? { borderTopLeftRadius: 'var(--radius-md)', borderBottomLeftRadius: 'var(--radius-md)' } : null),\n ...(i === items.length - 1 ? { borderTopRightRadius: 'var(--radius-md)', borderBottomRightRadius: 'var(--radius-md)' } : null),\n marginLeft: i === 0 ? 0 : -1 }\" />\n </template>\n </div>\n</template>\n"});
1
+ window.__KB_SRC__=Object.assign(window.__KB_SRC__||{},{"buttons/ActionChip.jsx":"import React from \"react\";\n\nconst chipTones = {\n success: { background: \"var(--success-bg)\", color: \"var(--success-text)\" },\n warning: { background: \"var(--warning-bg)\", color: \"var(--warning-text)\" },\n neutral: { background: \"var(--bg-hover)\", color: \"var(--text-body)\" },\n info: { background: \"var(--info-bg)\", color: \"var(--action-primary)\" },\n danger: { background: \"var(--danger-bg)\", color: \"var(--danger-text)\" },\n};\n\n/** Tinted bulk-action chip (\"Mark as New\", \"Mark as Overwrite\", \"Skip Selected\"). A control: it takes the region's tier height and text; `size` overrides it. */\nexport function ActionChip({ tone = \"neutral\", size, children, onClick, style }) {\n const [hover, setHover] = React.useState(false);\n return (\n <button type=\"button\" data-size={size} onClick={onClick} onMouseEnter={() => setHover(true)} onMouseLeave={() => setHover(false)}\n style={{ height: \"var(--control-h)\", padding: \"0 var(--control-px)\", borderRadius: \"var(--radius-md)\", border: \"none\", cursor: \"pointer\", fontFamily: \"var(--font-sans)\", fontWeight: \"var(--weight-medium)\", fontSize: \"var(--control-text)\", lineHeight: \"var(--control-leading)\", letterSpacing: \"var(--control-tracking)\", display: \"inline-flex\", alignItems: \"center\", filter: hover ? \"brightness(1.06) saturate(1.05)\" : \"none\", transition: \"var(--t-hover),filter var(--dur-fast) var(--ease-out)\", ...chipTones[tone], ...style }}>\n {children}\n </button>\n );\n}\n","buttons/ActionChip.vue":"<script setup>\nimport { ref, computed } from 'vue'\nconst chipTones = {\n success: { background: 'var(--success-bg)', color: 'var(--success-text)' },\n warning: { background: 'var(--warning-bg)', color: 'var(--warning-text)' },\n neutral: { background: 'var(--bg-hover)', color: 'var(--text-body)' },\n info: { background: 'var(--info-bg)', color: 'var(--action-primary)' },\n danger: { background: 'var(--danger-bg)', color: 'var(--danger-text)' },\n}\n// Tinted bulk-action chip (\"Mark as New\", \"Mark as Overwrite\", \"Skip Selected\"). A control: it takes the region's tier height and text; `size` overrides it.\nconst props = defineProps({ tone: { type: String, default: 'neutral' }, size: String, style: Object })\ndefineEmits(['click'])\nconst hover = ref(false)\nconst s = computed(() => ({ height: 'var(--control-h)', padding: '0 var(--control-px)', borderRadius: 'var(--radius-md)', border: 'none', cursor: 'pointer', fontFamily: 'var(--font-sans)', fontWeight: 'var(--weight-medium)', fontSize: 'var(--control-text)', lineHeight: 'var(--control-leading)', letterSpacing: 'var(--control-tracking)', display: 'inline-flex', alignItems: 'center', filter: hover.value ? 'brightness(1.06) saturate(1.05)' : 'none', transition: 'var(--t-hover),filter var(--dur-fast) var(--ease-out)', ...chipTones[props.tone], ...props.style }))\n</script>\n<template>\n <button type=\"button\" :data-size=\"size\" @click=\"$emit('click')\" @mouseenter=\"hover = true\" @mouseleave=\"hover = false\" :style=\"s\"><slot /></button>\n</template>\n","buttons/Button.jsx":"import React from \"react\";\nimport { Icon } from \"../icons/Icon.jsx\";\n\n/* Every dimension comes from the size tier the button sits in (tokens/layout.css): height, text, icon and padding\n switch together when a region declares data-size=\"sm\" | \"md\" | \"lg\". A `size` prop only stamps that attribute on\n the button itself — the default is to inherit, so siblings in one bar can never disagree. */\nconst btnBase = { display: \"inline-flex\", alignItems: \"center\", justifyContent: \"center\", gap: 6, height: \"var(--control-h)\", padding: \"0 var(--control-px)\", borderRadius: \"var(--radius-md)\", fontFamily: \"var(--font-sans)\", fontWeight: \"var(--weight-regular)\", fontSize: \"var(--control-text)\", lineHeight: \"var(--control-leading)\", letterSpacing: \"var(--control-tracking)\", border: \"1px solid transparent\", cursor: \"pointer\", whiteSpace: \"nowrap\", boxSizing: \"border-box\", background: \"transparent\", transition: \"var(--t-hover)\" };\nconst tierIcon = { width: \"var(--control-icon)\", height: \"var(--control-icon)\" };\n\nconst variants = {\n primary: { background: \"var(--action-primary)\", color: \"var(--on-accent)\" },\n dark: { background: \"var(--action-dark)\", color: \"var(--action-dark-fg)\" },\n outline: { background: \"var(--bg-surface)\", color: \"var(--text-body)\", borderColor: \"var(--border-control)\" },\n ghost: { color: \"var(--text-body)\" },\n \"primary-soft\": { background: \"var(--soft-bg)\", color: \"var(--action-primary)\", borderColor: \"var(--soft-border)\" },\n danger: { background: \"var(--danger)\", color: \"var(--on-accent)\" },\n \"danger-soft\": { background: \"var(--danger-bg)\", color: \"var(--danger-text)\" },\n text: { color: \"var(--text-secondary)\", padding: \"0\", height: \"auto\" },\n};\nconst hovers = {\n primary: \"var(--action-primary-hover)\", dark: \"var(--action-dark-hover)\",\n outline: \"var(--bg-hover)\", ghost: \"var(--bg-hover)\", \"primary-soft\": \"var(--soft-hover)\",\n danger: \"var(--danger-text)\", \"danger-soft\": \"var(--danger-soft-hover)\",\n};\n/** Press (mouse-down) fills — one step past hover. */\nconst presses = {\n primary: \"var(--action-primary-active)\", dark: \"var(--action-dark-active)\",\n outline: \"var(--bg-press)\", ghost: \"var(--bg-press)\", \"primary-soft\": \"var(--soft-active)\",\n danger: \"var(--danger-active)\", \"danger-soft\": \"var(--danger-soft-active)\",\n};\n/** Variants that change text color (+ underline) on hover instead of a background wash. */\nconst colorHoverVariants = { text: \"var(--text-heading)\" };\n\nfunction Spinner({ size, color }) {\n return <span style={{ display: \"inline-block\", width: size, height: size, ...(size ? null : tierIcon), borderRadius: \"var(--radius-full)\", border: \"2px solid currentColor\", borderTopColor: \"transparent\", opacity: .9, color, animation: \"kb-spin .7s linear infinite\", flexShrink: 0 }} />;\n}\n\n/** Keybricks button. variant: primary | dark | outline | ghost | primary-soft | danger | danger-soft | text; size: sm 24 | md 32 | lg 36 — omit it to inherit the region's tier (the default). Interaction states: hover (one step darker) · press (two steps, set via mouse-down) · keyboard focus ring · loading · disabled. */\nexport function Button({ variant = \"primary\", size, icon, iconSize, iconPosition = \"left\", medium, disabled, loading, fullWidth, iconOnly, label, pressed, focused, children, style, onClick, ...rest }) {\n const [hover, setHover] = React.useState(false);\n const [press, setPress] = React.useState(false);\n const [focus, setFocus] = React.useState(false);\n const busy = disabled || loading;\n const isPressed = press || pressed;\n const isFocused = focus || focused;\n const s = {\n ...btnBase, ...variants[variant],\n ...(medium ? { fontWeight: \"var(--weight-medium)\" } : null),\n ...(fullWidth ? { width: \"100%\" } : null),\n ...(iconOnly ? { width: \"var(--control-h)\", padding: 0, gap: 0 } : null),\n ...(busy ? { opacity: .55, cursor: \"default\" } : null),\n ...style,\n };\n if (!busy) {\n if (colorHoverVariants[variant]) {\n if (hover || isPressed) { s.color = colorHoverVariants[variant]; s.textDecoration = \"underline\"; }\n if (isPressed) s.opacity = .7;\n } else if (isPressed) {\n s.background = presses[variant];\n } else if (hover) {\n s.background = hovers[variant];\n }\n if (isFocused) s.boxShadow = \"var(--ring-focus)\";\n }\n const iconStyle = iconSize ? null : tierIcon;\n const leading = loading ? <Spinner size={iconSize} color={s.color} /> : (icon && iconPosition === \"left\" ? <Icon name={icon} size={iconSize || 16} style={iconStyle} /> : null);\n const trailing = !loading && icon && iconPosition === \"right\" ? <Icon name={icon} size={iconSize || 16} style={iconStyle} /> : null;\n return (\n <button type=\"button\" data-press=\"own\" data-size={size} style={s} disabled={busy} aria-label={iconOnly ? label : undefined} onClick={onClick}\n onMouseEnter={() => setHover(true)} onMouseLeave={() => { setHover(false); setPress(false); }}\n onMouseDown={() => setPress(true)} onMouseUp={() => setPress(false)}\n onKeyDown={(e) => { if (e.key === \" \" || e.key === \"Enter\") setPress(true); }} onKeyUp={() => setPress(false)}\n onFocus={(e) => { try { setFocus(e.target.matches(\":focus-visible\")); } catch (err) { setFocus(true); } }} onBlur={() => setFocus(false)} {...rest}>\n {leading}\n {iconOnly ? null : children}\n {trailing}\n </button>\n );\n}\n\n/** Attached row of Buttons sharing one outline (segmented action group). Children should be <Button variant=\"outline\"> or similar. */\nexport function ButtonGroup({ children, style }) {\n const items = React.Children.toArray(children);\n return (\n <div style={{ display: \"inline-flex\", ...style }}>\n {items.map((child, i) => React.cloneElement(child, {\n key: i,\n style: {\n ...(child.props.style || {}),\n borderRadius: 0,\n ...(i === 0 ? { borderTopLeftRadius: \"var(--radius-md)\", borderBottomLeftRadius: \"var(--radius-md)\" } : null),\n ...(i === items.length - 1 ? { borderTopRightRadius: \"var(--radius-md)\", borderBottomRightRadius: \"var(--radius-md)\" } : null),\n marginLeft: i === 0 ? 0 : -1,\n },\n }))}\n </div>\n );\n}\n","buttons/Button.vue":"<script setup>\nimport { px } from '../px.js'\nimport { computed, ref } from 'vue'\nimport Icon from '../icons/Icon.vue'\n\n// Every dimension comes from the size tier the button sits in (tokens/layout.css): height, text, icon and padding\n// switch together when a region declares data-size=\"sm\" | \"md\" | \"lg\". The `size` prop only stamps that attribute on\n// the button itself — the default is to inherit, so siblings in one bar can never disagree.\nconst btnBase = { display: 'inline-flex', alignItems: 'center', justifyContent: 'center', gap: '6px', height: 'var(--control-h)', padding: '0 var(--control-px)', borderRadius: 'var(--radius-md)', fontFamily: 'var(--font-sans)', fontWeight: 'var(--weight-regular)', fontSize: 'var(--control-text)', lineHeight: 'var(--control-leading)', letterSpacing: 'var(--control-tracking)', border: '1px solid transparent', cursor: 'pointer', whiteSpace: 'nowrap', boxSizing: 'border-box', background: 'transparent', transition: 'var(--t-hover)' }\nconst tierIcon = { width: 'var(--control-icon)', height: 'var(--control-icon)' }\nconst variants = {\n primary: { background: 'var(--action-primary)', color: 'var(--on-accent)' },\n dark: { background: 'var(--action-dark)', color: 'var(--action-dark-fg)' },\n outline: { background: 'var(--bg-surface)', color: 'var(--text-body)', borderColor: 'var(--border-control)' },\n ghost: { color: 'var(--text-body)' },\n 'primary-soft': { background: 'var(--soft-bg)', color: 'var(--action-primary)', borderColor: 'var(--soft-border)' },\n danger: { background: 'var(--danger)', color: 'var(--on-accent)' },\n 'danger-soft': { background: 'var(--danger-bg)', color: 'var(--danger-text)' },\n text: { color: 'var(--text-secondary)', padding: '0', height: 'auto' },\n}\nconst hovers = { primary: 'var(--action-primary-hover)', dark: 'var(--action-dark-hover)', outline: 'var(--bg-hover)', ghost: 'var(--bg-hover)', 'primary-soft': 'var(--soft-hover)', danger: 'var(--danger-text)', 'danger-soft': 'var(--danger-soft-hover)' }\nconst presses = { primary: 'var(--action-primary-active)', dark: 'var(--action-dark-active)', outline: 'var(--bg-press)', ghost: 'var(--bg-press)', 'primary-soft': 'var(--soft-active)', danger: 'var(--danger-active)', 'danger-soft': 'var(--danger-soft-active)' }\nconst colorHoverVariants = { text: 'var(--text-heading)' }\n\n// Button — variant: primary | dark | outline | ghost | primary-soft | danger | danger-soft | text; size: sm 24 | md 32 | lg 36 — omit it to inherit the region's tier (the default).\nconst props = defineProps({\n variant: { type: String, default: 'primary' }, size: String,\n icon: String, iconSize: Number, iconPosition: { type: String, default: 'left' },\n medium: Boolean, disabled: Boolean, loading: Boolean, fullWidth: Boolean, iconOnly: Boolean,\n label: String, pressed: Boolean, focused: Boolean, style: Object,\n})\ndefineEmits(['click'])\nconst hover = ref(false), press = ref(false), focus = ref(false)\nconst busy = computed(() => props.disabled || props.loading)\nconst isPressed = computed(() => press.value || props.pressed)\nconst isFocused = computed(() => focus.value || props.focused)\nconst s = computed(() => {\n const base = { ...btnBase, ...variants[props.variant],\n ...(props.medium ? { fontWeight: 'var(--weight-medium)' } : null),\n ...(props.fullWidth ? { width: '100%' } : null),\n ...(props.iconOnly ? { width: 'var(--control-h)', padding: 0, gap: 0 } : null),\n ...(busy.value ? { opacity: .55, cursor: 'default' } : null), ...props.style }\n if (!busy.value) {\n if (colorHoverVariants[props.variant]) {\n if (hover.value || isPressed.value) { base.color = colorHoverVariants[props.variant]; base.textDecoration = 'underline' }\n if (isPressed.value) base.opacity = .7\n } else if (isPressed.value) base.background = presses[props.variant]\n else if (hover.value) base.background = hovers[props.variant]\n if (isFocused.value) base.boxShadow = 'var(--ring-focus)'\n }\n return base\n})\nconst iSize = computed(() => props.iconSize || 16)\nconst iconStyle = computed(() => props.iconSize ? null : tierIcon)\n</script>\n<template>\n <button type=\"button\" data-press=\"own\" :data-size=\"size\" :style=\"s\" :disabled=\"busy\" :aria-label=\"iconOnly ? label : undefined\"\n @click=\"$emit('click')\" @mouseenter=\"hover = true\" @mouseleave=\"hover = false; press = false\"\n @mousedown=\"press = true\" @mouseup=\"press = false\" @keydown.enter=\"press = true\" @keydown.space=\"press = true\" @keyup=\"press = false\"\n @focus=\"focus = $event.target.matches(':focus-visible')\" @blur=\"focus = false\">\n <span v-if=\"loading\" :style=\"{ display: 'inline-block', width: px(iSize), height: px(iSize), ...iconStyle, borderRadius: 'var(--radius-full)', border: '2px solid currentColor', borderTopColor: 'transparent', opacity: .9, animation: 'kb-spin .7s linear infinite', flexShrink: 0 }\" />\n <Icon v-else-if=\"icon && iconPosition === 'left'\" :name=\"icon\" :size=\"iSize\" :style=\"iconStyle\" />\n <slot v-if=\"!iconOnly\" />\n <Icon v-if=\"!loading && icon && iconPosition === 'right'\" :name=\"icon\" :size=\"iSize\" :style=\"iconStyle\" />\n </button>\n</template>\n","buttons/IconButton.jsx":"import React from \"react\";\nimport { Icon } from \"../icons/Icon.jsx\";\n\n/* A square of the region's control height, icon at the tier's icon size (tokens/layout.css). `size` stamps\n data-size on the button; omit it to inherit — the default. \"xs\" is kept as an alias of \"sm\" for 1.x callers. */\nconst tierIcon = { width: \"var(--control-icon)\", height: \"var(--control-icon)\" };\n\n/** Square ghost icon button (toolbar/back/bell/view toggles). size: sm 24 | md 32 | lg 36 — omit to inherit the region's tier. danger tints red; loading shows a spinner and disables interaction. States: hover · press · keyboard focus ring · active (persistent toggle-on) · disabled. */\nexport function IconButton({ icon, size, active, muted, danger, disabled, loading, label, pressed, focused, style, onClick, ...rest }) {\n const [hover, setHover] = React.useState(false);\n const [press, setPress] = React.useState(false);\n const [focus, setFocus] = React.useState(false);\n const tier = size === \"xs\" ? \"sm\" : size;\n const busy = disabled || loading;\n const isPressed = (press || pressed) && !busy;\n const color = danger ? \"var(--danger)\" : muted ? \"var(--text-muted)\" : \"var(--text-body)\";\n const bg = isPressed ? (danger ? \"var(--danger-soft-active)\" : \"var(--bg-press)\")\n : active ? \"var(--bg-active)\"\n : hover && !busy ? (danger ? \"var(--danger-bg)\" : \"var(--bg-hover)\") : \"transparent\";\n return (\n <button type=\"button\" data-press=\"own\" data-size={tier} aria-label={label} disabled={busy} onClick={onClick}\n onMouseEnter={() => setHover(true)} onMouseLeave={() => { setHover(false); setPress(false); }}\n onMouseDown={() => setPress(true)} onMouseUp={() => setPress(false)}\n onKeyDown={(e) => { if (e.key === \" \" || e.key === \"Enter\") setPress(true); }} onKeyUp={() => setPress(false)}\n onFocus={(e) => { try { setFocus(e.target.matches(\":focus-visible\")); } catch (err) { setFocus(true); } }} onBlur={() => setFocus(false)}\n style={{ width: \"var(--control-h)\", height: \"var(--control-h)\", borderRadius: \"var(--radius-md)\", border: \"none\", cursor: busy ? \"default\" : \"pointer\", display: \"inline-flex\", alignItems: \"center\", justifyContent: \"center\", background: bg, color, opacity: busy ? .5 : 1, boxShadow: (focus || focused) && !busy ? \"var(--ring-focus)\" : \"none\", transition: \"var(--t-hover)\", padding: 0, flexShrink: 0, ...style }} {...rest}>\n {loading ? <span style={{ display: \"inline-block\", ...tierIcon, borderRadius: \"var(--radius-full)\", border: \"2px solid currentColor\", borderTopColor: \"transparent\", animation: \"kb-spin .7s linear infinite\" }} /> : <Icon name={icon} size={16} style={tierIcon} />}\n </button>\n );\n}\n","buttons/IconButton.vue":"<script setup>\nimport { ref, computed } from 'vue'\nimport Icon from '../icons/Icon.vue'\n// A square of the region's control height, icon at the tier's icon size (tokens/layout.css). `size` stamps data-size on\n// the button; omit it to inherit — the default. \"xs\" is kept as an alias of \"sm\" for 1.x callers.\nconst tierIcon = { width: 'var(--control-icon)', height: 'var(--control-icon)' }\n// Square ghost icon button (toolbar/back/bell/view toggles). size: sm 24 | md 32 | lg 36 — omit to inherit the region's tier.\nconst props = defineProps({ icon: String, size: String, active: Boolean, muted: Boolean, danger: Boolean, disabled: Boolean, loading: Boolean, label: String, pressed: Boolean, focused: Boolean, style: Object })\ndefineEmits(['click'])\nconst hover = ref(false), press = ref(false), focus = ref(false)\nconst tier = computed(() => props.size === 'xs' ? 'sm' : props.size)\nconst busy = computed(() => props.disabled || props.loading)\nconst isPressed = computed(() => (press.value || props.pressed) && !busy.value)\nconst color = computed(() => props.danger ? 'var(--danger)' : props.muted ? 'var(--text-muted)' : 'var(--text-body)')\nconst bg = computed(() => isPressed.value ? (props.danger ? 'var(--danger-soft-active)' : 'var(--bg-press)') : props.active ? 'var(--bg-active)' : (hover.value && !busy.value ? (props.danger ? 'var(--danger-bg)' : 'var(--bg-hover)') : 'transparent'))\nconst s = computed(() => ({ width: 'var(--control-h)', height: 'var(--control-h)', borderRadius: 'var(--radius-md)', border: 'none', cursor: busy.value ? 'default' : 'pointer', display: 'inline-flex', alignItems: 'center', justifyContent: 'center', background: bg.value, color: color.value, opacity: busy.value ? .5 : 1, boxShadow: (focus.value || props.focused) && !busy.value ? 'var(--ring-focus)' : 'none', transition: 'var(--t-hover)', padding: 0, flexShrink: 0, ...props.style }))\n</script>\n<template>\n <button type=\"button\" data-press=\"own\" :data-size=\"tier\" :aria-label=\"label\" :disabled=\"busy\" @click=\"$emit('click')\" @mouseenter=\"hover = true\" @mouseleave=\"hover = false; press = false\" @mousedown=\"press = true\" @mouseup=\"press = false\" @keydown.enter=\"press = true\" @keydown.space=\"press = true\" @keyup=\"press = false\" @focus=\"focus = $event.target.matches(':focus-visible')\" @blur=\"focus = false\" :style=\"s\">\n <span v-if=\"loading\" :style=\"{ display: 'inline-block', ...tierIcon, borderRadius: 'var(--radius-full)', border: '2px solid currentColor', borderTopColor: 'transparent', animation: 'kb-spin .7s linear infinite' }\" />\n <Icon v-else :name=\"icon\" :size=\"16\" :style=\"tierIcon\" />\n </button>\n</template>\n","buttons/ButtonGroup.vue":"<script setup>\nimport { useSlots, computed } from 'vue'\nconst props = defineProps({ style: Object })\nconst slots = useSlots()\nconst items = computed(() => slots.default ? slots.default() : [])\n</script>\n<template>\n <div :style=\"{ display: 'inline-flex', ...style }\">\n <template v-for=\"(child, i) in items\" :key=\"i\">\n <component :is=\"child\" :style=\"{ borderRadius: 0,\n ...(i === 0 ? { borderTopLeftRadius: 'var(--radius-md)', borderBottomLeftRadius: 'var(--radius-md)' } : null),\n ...(i === items.length - 1 ? { borderTopRightRadius: 'var(--radius-md)', borderBottomRightRadius: 'var(--radius-md)' } : null),\n marginLeft: i === 0 ? 0 : '-1px' }\" />\n </template>\n </div>\n</template>\n"});