@keyfunc/keybricks-ds 2.4.13 → 2.5.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 (145) hide show
  1. package/DEPLOY.md +4 -4
  2. package/INTEGRATION.md +28 -6
  3. package/_adherence.oxlintrc.json +10 -4
  4. package/_ds_bundle.js +20559 -0
  5. package/_src/icon-index.js +1 -0
  6. package/_src/unicons-index.js +1 -0
  7. package/_src/usage-code.js +737 -0
  8. package/changelog.js +17 -0
  9. package/components/_cards/accordion.card.html +1 -1
  10. package/components/_cards/action-chip.card.html +1 -1
  11. package/components/_cards/activity.card.html +1 -1
  12. package/components/_cards/alert.card.html +1 -1
  13. package/components/_cards/app-chrome.card.html +1 -1
  14. package/components/_cards/banner.card.html +1 -1
  15. package/components/_cards/breadcrumb.card.html +1 -1
  16. package/components/_cards/button-1-base.card.html +1 -1
  17. package/components/_cards/button-2-states.card.html +1 -1
  18. package/components/_cards/button-3-sizes-icons.card.html +1 -1
  19. package/components/_cards/button-4-group.card.html +1 -1
  20. package/components/_cards/cards-indicators.card.html +1 -1
  21. package/components/_cards/charts-1-sparkline.card.html +1 -1
  22. package/components/_cards/charts-10-gauge.card.html +1 -1
  23. package/components/_cards/charts-11-funnel.card.html +1 -1
  24. package/components/_cards/charts-12-treemap.card.html +1 -1
  25. package/components/_cards/charts-14-radar.card.html +1 -1
  26. package/components/_cards/charts-15-distribution.card.html +1 -1
  27. package/components/_cards/charts-16-pareto.card.html +1 -1
  28. package/components/_cards/charts-17-candlestick.card.html +1 -1
  29. package/components/_cards/charts-18-sankey.card.html +1 -1
  30. package/components/_cards/charts-19-chord.card.html +1 -1
  31. package/components/_cards/charts-2-line.card.html +1 -1
  32. package/components/_cards/charts-20-sunburst.card.html +1 -1
  33. package/components/_cards/charts-21-worldmap.card.html +1 -1
  34. package/components/_cards/charts-22-gantt.card.html +1 -1
  35. package/components/_cards/charts-23-bar3d.card.html +1 -1
  36. package/components/_cards/charts-24-pie3d.card.html +1 -1
  37. package/components/_cards/charts-25-surface3d.card.html +1 -1
  38. package/components/_cards/charts-26-scatter3d.card.html +1 -1
  39. package/components/_cards/charts-27-ribbon3d.card.html +1 -1
  40. package/components/_cards/charts-3-bar.card.html +1 -1
  41. package/components/_cards/charts-4-barlist.card.html +1 -1
  42. package/components/_cards/charts-5-donut.card.html +1 -1
  43. package/components/_cards/charts-6-scatter.card.html +1 -1
  44. package/components/_cards/charts-7-heatmap.card.html +1 -1
  45. package/components/_cards/charts-8-waterfall.card.html +1 -1
  46. package/components/_cards/charts-9-bullet.card.html +1 -1
  47. package/components/_cards/checkbox.card.html +1 -1
  48. package/components/_cards/codeblock.card.html +1 -1
  49. package/components/_cards/combobox.card.html +1 -1
  50. package/components/_cards/context-menu.card.html +1 -1
  51. package/components/_cards/date-picker.card.html +1 -1
  52. package/components/_cards/diffvalue.card.html +1 -1
  53. package/components/_cards/divider.card.html +1 -1
  54. package/components/_cards/drawer.card.html +1 -1
  55. package/components/_cards/dropdown-menu.card.html +1 -1
  56. package/components/_cards/dropzone.card.html +1 -1
  57. package/components/_cards/empty-state.card.html +1 -1
  58. package/components/_cards/icon-button.card.html +1 -1
  59. package/components/_cards/input.card.html +1 -1
  60. package/components/_cards/kbd.card.html +1 -1
  61. package/components/_cards/keyvalue.card.html +1 -1
  62. package/components/_cards/listrow.card.html +1 -1
  63. package/components/_cards/loading.card.html +1 -1
  64. package/components/_cards/log-viewer.card.html +1 -1
  65. package/components/_cards/multi-select.card.html +1 -1
  66. package/components/_cards/number-stepper.card.html +1 -1
  67. package/components/_cards/pagination.card.html +1 -1
  68. package/components/_cards/people.card.html +1 -1
  69. package/components/_cards/pipeline-node.card.html +1 -1
  70. package/components/_cards/pipeline-palette.card.html +1 -1
  71. package/components/_cards/radio.card.html +1 -1
  72. package/components/_cards/relative-time-picker.card.html +1 -1
  73. package/components/_cards/search.card.html +1 -1
  74. package/components/_cards/segmented-control.card.html +1 -1
  75. package/components/_cards/select.card.html +1 -1
  76. package/components/_cards/smart-table.card.html +1 -1
  77. package/components/_cards/spreadsheet.card.html +1 -1
  78. package/components/_cards/stepper.card.html +1 -1
  79. package/components/_cards/table.card.html +7 -2
  80. package/components/_cards/tabs.card.html +1 -1
  81. package/components/_cards/tag.card.html +1 -1
  82. package/components/_cards/textarea.card.html +1 -1
  83. package/components/_cards/timeline.card.html +1 -1
  84. package/components/_cards/toast.card.html +1 -1
  85. package/components/_cards/toggles.card.html +1 -1
  86. package/components/_cards/tooltip.card.html +1 -1
  87. package/components/_cards/tree.card.html +1 -1
  88. package/components/_shared/view-source.js +15 -185
  89. package/components/charts/BarList.jsx +1 -1
  90. package/components/charts/BarList.vue +8 -3
  91. package/components/charts/Ribbon3D.d.ts +2 -0
  92. package/components/charts/Scatter3D.d.ts +4 -0
  93. package/components/charts/SunburstChart.jsx +6 -1
  94. package/components/charts/SunburstChart.vue +7 -1
  95. package/components/charts/Surface3D.d.ts +2 -0
  96. package/components/charts/WorldMap.jsx +6 -1
  97. package/components/charts/WorldMap.vue +7 -1
  98. package/components/data/ListRow.d.ts +6 -3
  99. package/components/data/ListRow.jsx +21 -13
  100. package/components/data/ListRow.vue +25 -15
  101. package/components/data/Table.jsx +1 -1
  102. package/components/data/Table.vue +6 -2
  103. package/components/display/ProgressBar.jsx +1 -1
  104. package/components/display/ProgressBar.vue +1 -1
  105. package/components/feedback/Accordion.jsx +1 -1
  106. package/components/feedback/Accordion.vue +1 -1
  107. package/components/feedback/ContextMenu.jsx +3 -3
  108. package/components/feedback/ContextMenu.vue +4 -4
  109. package/components/feedback/Drawer.jsx +3 -3
  110. package/components/feedback/Drawer.vue +3 -3
  111. package/components/feedback/Timeline.vue +4 -1
  112. package/components/forms/Checkbox.d.ts +2 -0
  113. package/components/forms/Checkbox.jsx +9 -4
  114. package/components/forms/Checkbox.vue +6 -2
  115. package/components/forms/DatePicker.jsx +3 -1
  116. package/components/forms/DatePicker.vue +2 -1
  117. package/components/forms/Dropzone.jsx +1 -1
  118. package/components/forms/Dropzone.vue +1 -1
  119. package/components/forms/MultiSelect.jsx +5 -3
  120. package/components/forms/MultiSelect.vue +4 -3
  121. package/components/forms/Slider.jsx +1 -1
  122. package/components/forms/Slider.vue +1 -1
  123. package/components/forms/Switch.jsx +4 -4
  124. package/components/forms/Switch.vue +4 -4
  125. package/components/navigation/Sidebar.jsx +2 -2
  126. package/components/navigation/Sidebar.vue +2 -2
  127. package/components/navigation/TopBar.jsx +1 -1
  128. package/components/navigation/TopBar.vue +1 -1
  129. package/components/navigation/Tree.jsx +2 -2
  130. package/components/navigation/Tree.vue +14 -5
  131. package/components/pipeline/DataPreview.jsx +1 -1
  132. package/components/pipeline/DataPreview.vue +1 -1
  133. package/components/pipeline/NodeCard.jsx +1 -1
  134. package/components/pipeline/NodeCard.vue +1 -1
  135. package/components/pipeline/PaletteItem.vue +1 -1
  136. package/components/pipeline/PalettePanel.jsx +3 -3
  137. package/components/pipeline/PalettePanel.vue +2 -2
  138. package/components/tabs/SegmentedControl.jsx +2 -2
  139. package/components/tabs/SegmentedControl.vue +2 -2
  140. package/index.html +6 -56
  141. package/package.json +4 -2
  142. package/tokens/dark.css +1 -1
  143. package/tokens/interaction.css +4 -0
  144. package/tokens/layout.css +3 -0
  145. package/tokens/typography.css +2 -1
@@ -1,4 +1,4 @@
1
- <!-- @dsCard group="Components" viewport="700x690" name="Pipeline Palette" subtitle="240px component drawer — grid/list toggle · collapsible hued categories" -->
1
+ <!-- @dsCard group="Components" viewport="700x920" name="Pipeline Palette" subtitle="240px component drawer — grid/list toggle · collapsible hued categories" -->
2
2
  <!DOCTYPE html>
3
3
  <html><head><meta charset="utf-8"><script src="../_shared/frame-theme.js"></script><link rel="stylesheet" href="../../styles.css"><link rel="stylesheet" href="../../tokens/hover.css"><link rel="stylesheet" href="../_shared/card-kit.css">
4
4
  <script src="https://unpkg.com/react@18.3.1/umd/react.development.js" integrity="sha384-hD6/rw4ppMLGNu3tX5cjIb+uRZ7UkRJ6BPkLpg4hAu/6onKUg4lLsHAs9EBPT82L" crossorigin="anonymous"></script>
@@ -1,4 +1,4 @@
1
- <!-- @dsCard group="Components" viewport="700x1120" name="Radio Button" subtitle="Single choice from a small set — md/sm · description · disabled · row · card variant · arrow-key navigation" -->
1
+ <!-- @dsCard group="Components" viewport="700x1750" name="Radio Button" subtitle="Single choice from a small set — md/sm · description · disabled · row · card variant · arrow-key navigation" -->
2
2
  <!DOCTYPE html>
3
3
  <html><head><meta charset="utf-8"><script src="../_shared/frame-theme.js"></script><link rel="stylesheet" href="../../styles.css"><link rel="stylesheet" href="../../tokens/hover.css"><link rel="stylesheet" href="../_shared/card-kit.css">
4
4
  <script src="https://unpkg.com/react@18.3.1/umd/react.development.js" integrity="sha384-hD6/rw4ppMLGNu3tX5cjIb+uRZ7UkRJ6BPkLpg4hAu/6onKUg4lLsHAs9EBPT82L" crossorigin="anonymous"></script>
@@ -1,4 +1,4 @@
1
- <!-- @dsCard group="Components" viewport="700x720" name="Relative Time Picker" subtitle="Filter by how long ago · md / sm / lg · unlimited · disabled · localised labels" -->
1
+ <!-- @dsCard group="Components" viewport="700x880" name="Relative Time Picker" subtitle="Filter by how long ago · md / sm / lg · unlimited · disabled · localised labels" -->
2
2
  <!DOCTYPE html>
3
3
  <html><head><meta charset="utf-8"><script src="../_shared/frame-theme.js"></script><link rel="stylesheet" href="../../styles.css"><link rel="stylesheet" href="../../tokens/hover.css"><link rel="stylesheet" href="../_shared/card-kit.css">
4
4
  <script src="https://unpkg.com/react@18.3.1/umd/react.development.js" integrity="sha384-hD6/rw4ppMLGNu3tX5cjIb+uRZ7UkRJ6BPkLpg4hAu/6onKUg4lLsHAs9EBPT82L" crossorigin="anonymous"></script>
@@ -1,4 +1,4 @@
1
- <!-- @dsCard group="Components" viewport="700x520" name="Search Input" subtitle="Bordered · bare top-bar · with value/clear · disabled" -->
1
+ <!-- @dsCard group="Components" viewport="700x770" name="Search Input" subtitle="Bordered · bare top-bar · with value/clear · disabled" -->
2
2
  <!DOCTYPE html>
3
3
  <html><head><meta charset="utf-8"><script src="../_shared/frame-theme.js"></script><link rel="stylesheet" href="../../styles.css"><link rel="stylesheet" href="../../tokens/hover.css"><link rel="stylesheet" href="../_shared/card-kit.css">
4
4
  <script src="https://unpkg.com/react@18.3.1/umd/react.development.js" integrity="sha384-hD6/rw4ppMLGNu3tX5cjIb+uRZ7UkRJ6BPkLpg4hAu/6onKUg4lLsHAs9EBPT82L" crossorigin="anonymous"></script>
@@ -1,4 +1,4 @@
1
- <!-- @dsCard group="Components" viewport="700x1260" name="Segmented Control" subtitle="Mutually exclusive views in one inset track — md/sm · counts · icons · icon-only · disabled option · full width · ViewToggle" -->
1
+ <!-- @dsCard group="Components" viewport="700x1880" name="Segmented Control" subtitle="Mutually exclusive views in one inset track — md/sm · counts · icons · icon-only · disabled option · full width · ViewToggle" -->
2
2
  <!DOCTYPE html>
3
3
  <html><head><meta charset="utf-8"><script src="../_shared/frame-theme.js"></script><link rel="stylesheet" href="../../styles.css"><link rel="stylesheet" href="../../tokens/hover.css"><link rel="stylesheet" href="../_shared/card-kit.css">
4
4
  <script src="https://unpkg.com/react@18.3.1/umd/react.development.js" integrity="sha384-hD6/rw4ppMLGNu3tX5cjIb+uRZ7UkRJ6BPkLpg4hAu/6onKUg4lLsHAs9EBPT82L" crossorigin="anonymous"></script>
@@ -1,4 +1,4 @@
1
- <!-- @dsCard group="Components" viewport="700x430" name="Select" subtitle="md / sm · placeholder · disabled · error" -->
1
+ <!-- @dsCard group="Components" viewport="700x550" name="Select" subtitle="md / sm · placeholder · disabled · error" -->
2
2
  <!DOCTYPE html>
3
3
  <html><head><meta charset="utf-8"><script src="../_shared/frame-theme.js"></script><link rel="stylesheet" href="../../styles.css"><link rel="stylesheet" href="../../tokens/hover.css"><link rel="stylesheet" href="../_shared/card-kit.css">
4
4
  <script src="https://unpkg.com/react@18.3.1/umd/react.development.js" integrity="sha384-hD6/rw4ppMLGNu3tX5cjIb+uRZ7UkRJ6BPkLpg4hAu/6onKUg4lLsHAs9EBPT82L" crossorigin="anonymous"></script>
@@ -1,4 +1,4 @@
1
- <!-- @dsCard group="Components" viewport="700x1360" name="Smart Table (Database Grid)" subtitle="Frozen header and row numbers · default and compact density · typed fields · hue pills · aggregates · + New" -->
1
+ <!-- @dsCard group="Components" viewport="700x1470" name="Smart Table (Database Grid)" subtitle="Frozen header and row numbers · default and compact density · typed fields · hue pills · aggregates · + New" -->
2
2
  <!DOCTYPE html>
3
3
  <html><head><meta charset="utf-8"><script src="../_shared/frame-theme.js"></script><link rel="stylesheet" href="../../styles.css"><link rel="stylesheet" href="../../tokens/hover.css"><link rel="stylesheet" href="../_shared/card-kit.css">
4
4
  <script src="https://unpkg.com/react@18.3.1/umd/react.development.js" integrity="sha384-hD6/rw4ppMLGNu3tX5cjIb+uRZ7UkRJ6BPkLpg4hAu/6onKUg4lLsHAs9EBPT82L" crossorigin="anonymous"></script>
@@ -1,4 +1,4 @@
1
- <!-- @dsCard group="Components" viewport="924x560" name="Spreadsheet" subtitle="Formula bar · frozen headers · range selection · =SUM() · sheet tabs · status bar" -->
1
+ <!-- @dsCard group="Components" viewport="924x600" name="Spreadsheet" subtitle="Formula bar · frozen headers · range selection · =SUM() · sheet tabs · status bar" -->
2
2
  <!DOCTYPE html>
3
3
  <html><head><meta charset="utf-8"><script src="../_shared/frame-theme.js"></script><link rel="stylesheet" href="../../styles.css"><link rel="stylesheet" href="../../tokens/hover.css"><link rel="stylesheet" href="../_shared/card-kit.css">
4
4
  <script src="https://unpkg.com/react@18.3.1/umd/react.development.js" integrity="sha384-hD6/rw4ppMLGNu3tX5cjIb+uRZ7UkRJ6BPkLpg4hAu/6onKUg4lLsHAs9EBPT82L" crossorigin="anonymous"></script>
@@ -1,4 +1,4 @@
1
- <!-- @dsCard group="Components" viewport="700x450" name="Stepper" subtitle="Multi-step flow header — done · current · upcoming" -->
1
+ <!-- @dsCard group="Components" viewport="700x630" name="Stepper" subtitle="Multi-step flow header — done · current · upcoming" -->
2
2
  <!DOCTYPE html>
3
3
  <html><head><meta charset="utf-8"><script src="../_shared/frame-theme.js"></script><link rel="stylesheet" href="../../styles.css"><link rel="stylesheet" href="../../tokens/hover.css"><link rel="stylesheet" href="../_shared/card-kit.css">
4
4
  <script src="https://unpkg.com/react@18.3.1/umd/react.development.js" integrity="sha384-hD6/rw4ppMLGNu3tX5cjIb+uRZ7UkRJ6BPkLpg4hAu/6onKUg4lLsHAs9EBPT82L" crossorigin="anonymous"></script>
@@ -1,4 +1,4 @@
1
- <!-- @dsCard group="Components" viewport="700x9720" name="Table" subtitle="Anatomy · densities · cell types (display · editable · per tier) · two-line name · sorting · selection · frames · column resize · states · composition" -->
1
+ <!-- @dsCard group="Components" viewport="700x11200" name="Table" subtitle="Anatomy · densities · cell types (display · editable · per tier) · two-line name · sorting · selection · frames · column resize · states · composition" -->
2
2
  <!DOCTYPE html>
3
3
  <html><head><meta charset="utf-8"><script src="../_shared/frame-theme.js"></script><link rel="stylesheet" href="../../styles.css"><link rel="stylesheet" href="../../tokens/hover.css"><link rel="stylesheet" href="../_shared/card-kit.css">
4
4
  <script src="https://unpkg.com/react@18.3.1/umd/react.development.js" integrity="sha384-hD6/rw4ppMLGNu3tX5cjIb+uRZ7UkRJ6BPkLpg4hAu/6onKUg4lLsHAs9EBPT82L" crossorigin="anonymous"></script>
@@ -111,6 +111,9 @@ const TIER_COLS = (t) => [
111
111
  { key: "act", label: "On conflict", width: 160, render: v => <Live init={v}>{(x, set) => <Select options={["New", "Overwrite", "Skip"]} value={x} onChange={(e) => set(e && e.target ? e.target.value : e)} style={{ width: "100%", minWidth: 124 }} />}</Live> },
112
112
  { key: "trend", label: "Trend", render: v => <Sparkline values={v} width={FIT[t].sp[0]} height={FIT[t].sp[1]} tone="auto" /> },
113
113
  ];
114
+ const TIER_COLS_SM = TIER_COLS("sm");
115
+ const TIER_COLS_MD = TIER_COLS("md");
116
+ const TIER_COLS_LG = TIER_COLS("lg");
114
117
  const SPEC_COLS = [{ key: "part", label: "In the cell", width: 230 }, { key: "sm", label: "sm", mono: true, width: 100 }, { key: "md", label: "md", mono: true, width: 90 }, { key: "lg", label: "lg", mono: true, width: 90 }, { key: "how", label: "Sized by" }];
115
118
  const SPEC_ROWS = [
116
119
  { part: "Row", sm: "36", md: "40", lg: "48", how: "table size" },
@@ -204,7 +207,9 @@ function Sheet() {
204
207
  <div className="note">Controls fill their column (<code>width: 100%</code>) and sit 4px from the row edges — the row is the tier's bar height, the control the tier's control height. For a grid the user edits cell by cell, use <b>Spreadsheet</b> or <b>Smart Table</b> instead.</div>
205
208
  </Case>
206
209
  <Case k="per tier — the same cells at sm · md · lg">
207
- {["sm", "md", "lg"].map(t => <div key={t} style={{ paddingBottom: 12 }}><span className="k">{t} · {{ sm: "36", md: "40", lg: "48" }[t]}px rows · Avatar {FIT[t].av} · Sparkline {FIT[t].sp.join("×")}</span><Table size={t} bordered columns={TIER_COLS(t)} rows={TIER_ROWS} /></div>)}
210
+ <div style={{ paddingBottom: 12 }}><span className="k">sm · 36px rows · Avatar {FIT.sm.av} · Sparkline {FIT.sm.sp.join("×")}</span><Table size="sm" bordered columns={TIER_COLS_SM} rows={TIER_ROWS} /></div>
211
+ <div style={{ paddingBottom: 12 }}><span className="k">md · 40px rows · Avatar {FIT.md.av} · Sparkline {FIT.md.sp.join("×")}</span><Table size="md" bordered columns={TIER_COLS_MD} rows={TIER_ROWS} /></div>
212
+ <div style={{ paddingBottom: 12 }}><span className="k">lg · 48px rows · Avatar {FIT.lg.av} · Sparkline {FIT.lg.sp.join("×")}</span><Table size="lg" bordered columns={TIER_COLS_LG} rows={TIER_ROWS} /></div>
208
213
  </Case>
209
214
  <Case k="sizes per tier — px">
210
215
  <Table size="sm" bordered columns={SPEC_COLS} rows={SPEC_ROWS} />
@@ -1,4 +1,4 @@
1
- <!-- @dsCard group="Components" viewport="700x810" name="Tabs" subtitle="Underline tabs · panel tabs · pill filter tabs · counts on every kind" -->
1
+ <!-- @dsCard group="Components" viewport="700x1130" name="Tabs" subtitle="Underline tabs · panel tabs · pill filter tabs · counts on every kind" -->
2
2
  <!DOCTYPE html>
3
3
  <html><head><meta charset="utf-8"><script src="../_shared/frame-theme.js"></script><link rel="stylesheet" href="../../styles.css"><link rel="stylesheet" href="../../tokens/hover.css"><link rel="stylesheet" href="../_shared/card-kit.css">
4
4
  <script src="https://unpkg.com/react@18.3.1/umd/react.development.js" integrity="sha384-hD6/rw4ppMLGNu3tX5cjIb+uRZ7UkRJ6BPkLpg4hAu/6onKUg4lLsHAs9EBPT82L" crossorigin="anonymous"></script>
@@ -1,4 +1,4 @@
1
- <!-- @dsCard group="Components" viewport="700x300" name="Tag" subtitle="Removable filter tags — distinct from Badge/ActionChip" -->
1
+ <!-- @dsCard group="Components" viewport="700x450" name="Tag" subtitle="Removable filter tags — distinct from Badge/ActionChip" -->
2
2
  <!DOCTYPE html>
3
3
  <html><head><meta charset="utf-8"><script src="../_shared/frame-theme.js"></script><link rel="stylesheet" href="../../styles.css"><link rel="stylesheet" href="../../tokens/hover.css"><link rel="stylesheet" href="../_shared/card-kit.css">
4
4
  <script src="https://unpkg.com/react@18.3.1/umd/react.development.js" integrity="sha384-hD6/rw4ppMLGNu3tX5cjIb+uRZ7UkRJ6BPkLpg4hAu/6onKUg4lLsHAs9EBPT82L" crossorigin="anonymous"></script>
@@ -1,4 +1,4 @@
1
- <!-- @dsCard group="Components" viewport="924x520" name="Textarea" subtitle="Default · character count · over the limit · disabled" -->
1
+ <!-- @dsCard group="Components" viewport="924x680" name="Textarea" subtitle="Default · character count · over the limit · disabled" -->
2
2
  <!DOCTYPE html>
3
3
  <html><head><meta charset="utf-8"><script src="../_shared/frame-theme.js"></script><link rel="stylesheet" href="../../styles.css"><link rel="stylesheet" href="../../tokens/hover.css"><link rel="stylesheet" href="../_shared/card-kit.css">
4
4
  <script src="https://unpkg.com/react@18.3.1/umd/react.development.js" integrity="sha384-hD6/rw4ppMLGNu3tX5cjIb+uRZ7UkRJ6BPkLpg4hAu/6onKUg4lLsHAs9EBPT82L" crossorigin="anonymous"></script>
@@ -1,4 +1,4 @@
1
- <!-- @dsCard group="Components" viewport="700x350" name="Timeline" subtitle="Vertical activity timeline — toned icon nodes on a hairline spine" -->
1
+ <!-- @dsCard group="Components" viewport="700x390" name="Timeline" subtitle="Vertical activity timeline — toned icon nodes on a hairline spine" -->
2
2
  <!DOCTYPE html>
3
3
  <html><head><meta charset="utf-8"><script src="../_shared/frame-theme.js"></script><link rel="stylesheet" href="../../styles.css"><link rel="stylesheet" href="../../tokens/hover.css"><link rel="stylesheet" href="../_shared/card-kit.css">
4
4
  <script src="https://unpkg.com/react@18.3.1/umd/react.development.js" integrity="sha384-hD6/rw4ppMLGNu3tX5cjIb+uRZ7UkRJ6BPkLpg4hAu/6onKUg4lLsHAs9EBPT82L" crossorigin="anonymous"></script>
@@ -1,4 +1,4 @@
1
- <!-- @dsCard group="Components" viewport="700x450" name="Toast" subtitle="Tones · with/without meta · live ToastStack demo" -->
1
+ <!-- @dsCard group="Components" viewport="700x800" name="Toast" subtitle="Tones · with/without meta · live ToastStack demo" -->
2
2
  <!DOCTYPE html>
3
3
  <html><head><meta charset="utf-8"><script src="../_shared/frame-theme.js"></script><link rel="stylesheet" href="../../styles.css"><link rel="stylesheet" href="../../tokens/hover.css"><link rel="stylesheet" href="../_shared/card-kit.css">
4
4
  <script src="https://unpkg.com/react@18.3.1/umd/react.development.js" integrity="sha384-hD6/rw4ppMLGNu3tX5cjIb+uRZ7UkRJ6BPkLpg4hAu/6onKUg4lLsHAs9EBPT82L" crossorigin="anonymous"></script>
@@ -1,4 +1,4 @@
1
- <!-- @dsCard group="Components" viewport="700x1670" name="Toggle Switch" subtitle="Binary settings pill — sizes · semantic red→green · glyph knobs · inline text · captions · async loading" -->
1
+ <!-- @dsCard group="Components" viewport="700x2780" name="Toggle Switch" subtitle="Binary settings pill — sizes · semantic red→green · glyph knobs · inline text · captions · async loading" -->
2
2
  <!DOCTYPE html>
3
3
  <html><head><meta charset="utf-8"><script src="../_shared/frame-theme.js"></script><link rel="stylesheet" href="../../styles.css"><link rel="stylesheet" href="../../tokens/hover.css"><link rel="stylesheet" href="../_shared/card-kit.css">
4
4
  <script src="https://unpkg.com/react@18.3.1/umd/react.development.js" integrity="sha384-hD6/rw4ppMLGNu3tX5cjIb+uRZ7UkRJ6BPkLpg4hAu/6onKUg4lLsHAs9EBPT82L" crossorigin="anonymous"></script>
@@ -1,4 +1,4 @@
1
- <!-- @dsCard group="Components" viewport="700x360" name="Tooltip" subtitle="Placements — top · bottom · left · right, on icon and text triggers" -->
1
+ <!-- @dsCard group="Components" viewport="700x510" name="Tooltip" subtitle="Placements — top · bottom · left · right, on icon and text triggers" -->
2
2
  <!DOCTYPE html>
3
3
  <html><head><meta charset="utf-8"><script src="../_shared/frame-theme.js"></script><link rel="stylesheet" href="../../styles.css"><link rel="stylesheet" href="../../tokens/hover.css"><link rel="stylesheet" href="../_shared/card-kit.css">
4
4
  <script src="https://unpkg.com/react@18.3.1/umd/react.development.js" integrity="sha384-hD6/rw4ppMLGNu3tX5cjIb+uRZ7UkRJ6BPkLpg4hAu/6onKUg4lLsHAs9EBPT82L" crossorigin="anonymous"></script>
@@ -1,4 +1,4 @@
1
- <!-- @dsCard group="Components" viewport="700x2820" name="Tree" subtitle="Cascading checkboxes · disabled nodes · lines · async load · search · drag · reorder · keyboard" -->
1
+ <!-- @dsCard group="Components" viewport="700x3170" name="Tree" subtitle="Cascading checkboxes · disabled nodes · lines · async load · search · drag · reorder · keyboard" -->
2
2
  <!DOCTYPE html>
3
3
  <html><head><meta charset="utf-8"><script src="../_shared/frame-theme.js"></script><link rel="stylesheet" href="../../styles.css"><link rel="stylesheet" href="../../tokens/hover.css"><link rel="stylesheet" href="../_shared/card-kit.css">
4
4
  <script src="https://unpkg.com/react@18.3.1/umd/react.development.js" integrity="sha384-hD6/rw4ppMLGNu3tX5cjIb+uRZ7UkRJ6BPkLpg4hAu/6onKUg4lLsHAs9EBPT82L" crossorigin="anonymous"></script>
@@ -1,194 +1,24 @@
1
1
  (function(){
2
- var bundles = {};
3
- /* Component source is loaded on demand, one script per folder (_src/src-<dir>.js at the project root).
4
- It lives outside components/ so the design-system compiler keeps it out of _ds_bundle.js — ~870 KB of
5
- source text every card and the home page would otherwise download and parse just to show View Code.
6
- _src/ also holds the icon search indexes (icon-index.js, unicons-index.js) that only the icon gallery cards load;
7
- assets/icons/*.json keep the same data for apps.
8
- A <script> tag works from file:// and from any host; fetch() of a sibling source file does not. */
9
- function loadBundle(dir, done){
10
- if (!dir || bundles[dir] === 'done') return done();
11
- if (bundles[dir]) { bundles[dir].push(done); return; }
12
- bundles[dir] = [done];
13
- var s = document.createElement('script');
14
- s.src = '../../_src/src-' + dir + '.js';
15
- s.onload = s.onerror = function(){
16
- var q = bundles[dir]; bundles[dir] = 'done';
17
- q.forEach(function(fn){ fn(); });
18
- };
2
+ /* Cards call KBViewSource.mount(selector) once they render. It adds the "Show code" bar under each example —
3
+ the React / Vue 3 code that builds it, generated by _src/usage-code.js (loaded on demand, kept out of _ds_bundle.js).
4
+ The site does not show components' own source: developers use the package, and the source ships in it (and in GitLab).
5
+ Inside the documentation site the card also follows the site's theme (the host posts { kb: 'theme' }). */
6
+ function loadUsage(sel){
7
+ if (window.KBUsage) { window.KBUsage.attach(sel); return; }
8
+ var s = document.createElement('script'); s.src = '../../_src/usage-code.js';
9
+ s.onload = function(){ if (window.KBUsage) window.KBUsage.attach(sel); };
19
10
  document.head.appendChild(s);
20
11
  }
21
- function esc(s){return s;}
22
- function iconSvg(){return '<svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="m18 16 4-4-4-4"/><path d="m6 8-4 4 4 4"/><path d="m14.5 4-5 16"/></svg>';}
23
- function copySvg(){return '<svg width="11" height="11" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect width="14" height="14" x="8" y="8" rx="2"/><path d="M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2"/></svg>';}
24
- function prettyHtml(html){
25
- var s = html.replace(/></g,'>\n<');
26
- var lines = s.split('\n'), indent=0, out=[];
27
- for (var i=0;i<lines.length;i++){
28
- var line = lines[i].trim(); if(!line) continue;
29
- var closing = /^<\//.test(line);
30
- if (closing) indent = Math.max(0, indent-1);
31
- out.push(' '.repeat(indent) + line);
32
- var selfClosing = /\/>$/.test(line) || /^<(br|img|input|hr)\b/i.test(line);
33
- var isOpen = /^<[a-zA-Z]/.test(line) && !closing && !selfClosing;
34
- if (isOpen) indent++;
35
- }
36
- return out.join('\n');
37
- }
38
- function resolveSrc(path, framework, cb){
39
- var p = framework === 'vue' ? path.replace(/\.jsx$/, '.vue') : path;
40
- if (framework === 'vue' && /\.jsx$/.test(path)) { var src = window.__KB_SRC_MANIFEST__ && window.__KB_SRC_MANIFEST__[path]; if (src && src.vue) p = src.vue; }
41
- var key = p.replace(/^\.\.\//, '');
42
- function hit(){ return window.__KB_SRC__ && window.__KB_SRC__[key] != null ? window.__KB_SRC__[key] : null; }
43
- var t = hit(); if (t != null) return cb(t);
44
- loadBundle(key.split('/')[0], function(){
45
- var t = hit(); if (t != null) return cb(t);
46
- fetch(p).then(function(r){ if (!r.ok) throw 0; return r.text(); }).then(cb)
47
- .catch(function(){ cb('// ' + p + ' has no standalone source file in this export.\n// It is defined inside _ds_bundle.js — the live demo above is the real component.'); });
48
- });
49
- }
50
- function serve(files){
12
+ var listening = false;
13
+ function mount(rootSelector){
14
+ loadUsage(rootSelector);
51
15
  var framed; try { framed = window.parent !== window; } catch(e){ framed = true; }
52
- if (!framed) return false;
53
- var list = files.map(function(f){ var o = { name: f.name, path: f.path }; if (f.vue) o.vue = f.vue; if (f.vueName) o.vueName = f.vueName; if (f.vueOnly) o.vueOnly = true; if (f.reactOnly) o.reactOnly = true; return o; });
54
- window.__KB_SRC_MANIFEST__ = {}; list.forEach(function(o){ window.__KB_SRC_MANIFEST__[o.path] = o; });
16
+ if (!framed || listening) return;
17
+ listening = true;
55
18
  window.addEventListener('message', function(e){
56
- var m = e.data; if (!m) return;
57
- if (m.kb === 'src-get') {
58
- resolveSrc(m.path, m.framework, function(text){
59
- try { window.parent.postMessage({ kb:'src-text', path:m.path, framework:m.framework, text:text }, '*'); } catch(err){}
60
- });
61
- } else if (m.kb === 'theme' && m.theme) {
62
- document.documentElement.setAttribute('data-theme', m.theme);
63
- document.documentElement.style.colorScheme = m.theme;
64
- }
65
- });
66
- function send(){ try { window.parent.postMessage({ kb:'src-manifest', files:list }, '*'); } catch(e){} }
67
- send(); setTimeout(send, 250); setTimeout(send, 900);
68
- return true;
69
- }
70
- function mount(rootSelector, files){
71
- var root = document.querySelector(rootSelector);
72
- if (!root || !root.parentNode) return;
73
- /* Inside the design-system site the host page renders the View Code UI below the
74
- component box, so the card only serves source text over postMessage. This path
75
- also works from file://, where the host cannot touch this document at all. */
76
- if (serve(files)) return;
77
- var wrap = document.createElement('div');
78
- wrap.setAttribute('data-kb-viewsource','1');
79
- wrap.style.cssText = 'margin:16px 0 4px;font-family:var(--font-sans,sans-serif)';
80
- var btn = document.createElement('button');
81
- btn.type = 'button';
82
- btn.innerHTML = iconSvg() + '<span style="margin-left:6px">View Code</span>';
83
- btn.style.cssText = 'display:inline-flex;align-items:center;height:28px;box-sizing:border-box;padding:0 8px;border-radius:var(--radius-md,8px);border:1px solid var(--border-control,#e5e5e5);background:var(--bg-surface,#fff);color:var(--text-secondary,#737373);font-size:var(--text-xs,12px);line-height:var(--leading-xs,16px);font-family:var(--font-sans,sans-serif);cursor:pointer;';
84
- var panel = document.createElement('div');
85
- panel.style.cssText = 'display:none;margin-top:10px;border:1px solid var(--border-control,#e5e5e5);border-radius:8px;overflow:hidden;background:var(--bg-inset,#fafafa);';
86
- var headRow = document.createElement('div');
87
- headRow.style.cssText = 'display:flex;align-items:center;justify-content:space-between;background:var(--bg-surface,#fff);border-bottom:1px solid var(--border-subtle,#f0f0f0);';
88
- var tabBar = document.createElement('div');
89
- tabBar.style.cssText = 'display:flex;overflow-x:auto;flex:1;';
90
- var fwBar = document.createElement('div');
91
- fwBar.style.cssText = 'display:flex;align-items:center;flex-shrink:0;height:28px;box-sizing:border-box;gap:2px;padding:2px;margin:0 8px;border-radius:var(--radius-md,8px);background:var(--bg-inset,#fafafa);border:1px solid var(--border-control,#e5e5e5);';
92
- var framework = 'react';
93
- ['React','Vue 3'].forEach(function(fw){
94
- var fb = document.createElement('button');
95
- fb.type = 'button'; fb.textContent = fw;
96
- fb.style.cssText = 'display:inline-flex;align-items:center;height:22px;font-size:var(--text-xs,12px);line-height:var(--leading-xs,16px);font-weight:var(--weight-medium,500);font-family:var(--font-sans,sans-serif);padding:0 6px;border-radius:var(--radius-sm,4px);border:none;background:transparent;color:var(--text-secondary,#737373);cursor:pointer;white-space:nowrap;';
97
- fb.onclick = function(){
98
- framework = fw === 'Vue 3' ? 'vue' : 'react';
99
- Array.prototype.forEach.call(fwBar.children, function(el){
100
- var on = el.textContent === fw;
101
- el.style.background = on ? 'var(--bg-surface,#fff)' : 'transparent'; el.style.boxShadow = on ? '0 1px 2px rgba(0,0,0,.08)' : 'none';
102
- el.style.color = on ? 'var(--text-heading,#0a0a0a)' : 'var(--text-secondary,#737373)';
103
-
104
- });
105
- Array.prototype.forEach.call(tabBar.children, function(el, i){
106
- if (tabs[i].html) return;
107
- el.textContent = framework === 'vue' ? (tabs[i].vueName || tabs[i].name.replace(/\.jsx$/, '.vue')) : tabs[i].name;
108
- el.style.display = (framework === 'vue' && tabs[i].reactOnly) || (framework === 'react' && tabs[i].vueOnly) ? 'none' : '';
109
- });
110
- if (active !== -1 && tabBar.children[active].style.display === 'none') { for (var k = 0; k < tabs.length; k++) if (tabBar.children[k].style.display !== 'none') { selectTab(k); break; } }
111
- else if (active !== -1) selectTab(active);
112
- };
113
- fwBar.appendChild(fb);
114
- });
115
- fwBar.firstChild.style.background = 'var(--bg-surface,#fff)'; fwBar.firstChild.style.boxShadow = '0 1px 2px rgba(0,0,0,.08)';
116
- fwBar.firstChild.style.color = 'var(--text-heading,#0a0a0a)';
117
-
118
- headRow.appendChild(tabBar); headRow.appendChild(fwBar);
119
- var body = document.createElement('div');
120
- var tabs = files.slice();
121
- var cache = {}, active = -1;
122
- function renderTab(t){
123
- var box = document.createElement('div');
124
- box.style.position = 'relative';
125
- var pre = document.createElement('pre');
126
- pre.style.cssText = 'margin:0;padding:14px 70px 14px 16px;overflow:auto;max-height:380px;font-family:var(--font-mono,monospace);font-size:var(--text-code,12px);line-height:var(--leading-code,18px);color:var(--text-body,#525252);white-space:pre;';
127
- var copyBtn = document.createElement('button');
128
- copyBtn.type = 'button';
129
- copyBtn.innerHTML = copySvg() + '<span style="margin-left:4px">Copy</span>';
130
- copyBtn.style.cssText = 'position:absolute;top:8px;right:10px;display:inline-flex;align-items:center;height:28px;box-sizing:border-box;padding:0 8px;border-radius:var(--radius-md,8px);background:var(--bg-surface,#fff);color:var(--text-secondary,#737373);font-size:var(--text-xs,12px);line-height:var(--leading-xs,16px);font-family:var(--font-sans,sans-serif);cursor:pointer;border:1px solid var(--border-control,#e5e5e5);';
131
- function setText(text){
132
- pre.textContent = text;
133
- copyBtn.onclick = function(){
134
- try { navigator.clipboard.writeText(text); } catch(e){}
135
- var old = copyBtn.innerHTML;
136
- copyBtn.innerHTML = 'Copied';
137
- setTimeout(function(){ copyBtn.innerHTML = old; }, 1200);
138
- };
139
- }
140
- {
141
- var p = framework === 'vue' ? (t.vue || t.path.replace(/\.jsx$/, '.vue')) : t.path;
142
- var key = p.replace(/^\.\.\//, '');
143
- var fromCache = function(){
144
- if (window.__KB_SRC__ && window.__KB_SRC__[key] != null) { setText(window.__KB_SRC__[key]); return true; }
145
- return false;
146
- };
147
- if (!fromCache()) {
148
- pre.textContent = 'Loading…';
149
- // Sources are shipped as one script per folder so this works over file:// too,
150
- // where fetch() to a sibling file is blocked. fetch is only the last resort.
151
- loadBundle(key.split('/')[0], function(){
152
- if (fromCache()) return;
153
- fetch(p).then(function(r){ if (!r.ok) throw 0; return r.text(); })
154
- .then(setText)
155
- .catch(function(){ pre.textContent = '// ' + p + ' has no standalone source file in this export.\n// It is defined inside _ds_bundle.js — the live demo above is the real component.'; });
156
- });
157
- }
158
- }
159
- box.appendChild(pre); box.appendChild(copyBtn);
160
- return box;
161
- }
162
- function selectTab(idx){
163
- active = idx;
164
- Array.prototype.forEach.call(tabBar.children, function(el, i){
165
- el.style.color = i === idx ? 'var(--text-heading,#171717)' : 'var(--text-secondary,#737373)';
166
- el.style.borderBottom = i === idx ? '2px solid var(--action-primary,#155dfc)' : '2px solid transparent';
167
- });
168
- body.innerHTML = '';
169
- body.appendChild(renderTab(tabs[idx]));
170
- }
171
- tabs.forEach(function(t, i){
172
- var tb = document.createElement('button');
173
- tb.type = 'button';
174
- tb.textContent = t.name;
175
- if (t.vueOnly) tb.style.display = 'none';
176
- tb.style.cssText = 'padding:8px 12px;border:none;background:transparent;font-size:var(--text-xs,12px);line-height:var(--leading-xs,16px);font-family:var(--font-sans,sans-serif);cursor:pointer;white-space:nowrap;margin-bottom:-1px;border-bottom:2px solid transparent;';
177
- tb.onclick = function(){ selectTab(i); };
178
- tabBar.appendChild(tb);
19
+ var m = e.data;
20
+ if (m && m.kb === 'theme' && m.theme) { document.documentElement.setAttribute('data-theme', m.theme); document.documentElement.style.colorScheme = m.theme; }
179
21
  });
180
- panel.appendChild(headRow);
181
- panel.appendChild(body);
182
- var open = false;
183
- btn.onclick = function(){
184
- open = !open;
185
- panel.style.display = open ? 'block' : 'none';
186
- btn.querySelector('span').textContent = open ? 'Hide Code' : 'View Code';
187
- if (open && active === -1) selectTab(0);
188
- };
189
- wrap.appendChild(btn);
190
- wrap.appendChild(panel);
191
- root.parentNode.appendChild(wrap);
192
22
  }
193
23
  window.KBViewSource = { mount: mount };
194
24
  })();
@@ -13,7 +13,7 @@ export function BarList({ rows = [], max, width = 360, valueFormat = fmtNum, sho
13
13
  <div style={{ display: "flex", flexDirection: "column", gap: 10, width, ...style }}>
14
14
  {rows.map((r) => (
15
15
  <div key={r.label} onMouseEnter={interactive ? () => setHover(r.label) : undefined} onMouseLeave={interactive ? () => setHover(null) : undefined}
16
- onClick={onSelect ? () => onSelect(r) : undefined}
16
+ onClick={onSelect ? () => onSelect(r) : undefined} role={onSelect ? "button" : undefined} tabIndex={onSelect ? 0 : undefined} onKeyDown={onSelect ? (e) => { if (e.key === "Enter" || e.key === " ") { e.preventDefault(); onSelect(r); } } : undefined}
17
17
  style={{ opacity: hover == null || hover === r.label ? 1 : 0.5, cursor: onSelect ? "pointer" : "default", transition: "var(--t-hover)" }}>
18
18
  <div style={{ display: "flex", alignItems: "baseline", gap: 8, paddingBottom: 4 }}>
19
19
  <span style={{ fontFamily: "var(--font-sans)", fontSize: "var(--text-xs)", color: "var(--text-body)", whiteSpace: "nowrap", overflow: "hidden", textOverflow: "ellipsis" }}>{r.label}</span>
@@ -1,16 +1,21 @@
1
1
  <script setup>
2
- import { computed, ref } from 'vue'
2
+ import { computed, ref, getCurrentInstance } from 'vue'
3
3
  import { fmtNum } from './chart-geometry.js'
4
4
  // Horizontal labeled bars — top-N rankings, budget consumption.
5
5
  const props = defineProps({ rows:{type:Array,default:()=>[]}, max:Number, width:{type:Number,default:360}, barHeight:{type:Number,default:8}, showTrack:{type:Boolean,default:true}, valueFormat:{type:Function,default:fmtNum}, interactive:{type:Boolean,default:true}, style:Object })
6
6
  const top = computed(() => props.max!=null ? props.max : Math.max(1,...props.rows.map(r=>r.value)))
7
7
  const total = computed(() => props.rows.reduce((s,r)=>s+r.value,0)||1)
8
8
  const hover = ref(null)
9
+ // @select(row) — like React's onSelect: a listener makes each row a button (click, Enter / Space).
10
+ const emit = defineEmits(['select'])
11
+ const inst = getCurrentInstance()
12
+ const selectable = computed(() => !!(inst && inst.vnode.props && inst.vnode.props.onSelect))
13
+ function pick(r) { if (selectable.value) emit('select', r) }
9
14
  </script>
10
15
  <template>
11
16
  <div :style="{display:'flex',flexDirection:'column',gap:'10px',width:width+'px',...style}">
12
- <div v-for="r in rows" :key="r.label" @mouseenter="interactive && (hover=r.label)" @mouseleave="interactive && (hover=null)"
13
- :style="{opacity:hover==null||hover===r.label?1:0.5,transition:'var(--t-hover)'}">
17
+ <div v-for="r in rows" :key="r.label" @mouseenter="interactive && (hover=r.label)" @mouseleave="interactive && (hover=null)" :role="selectable ? 'button' : undefined" :tabindex="selectable ? 0 : undefined" @click="pick(r)" @keydown.enter.prevent="pick(r)" @keydown.space.prevent="pick(r)"
18
+ :style="{opacity:hover==null||hover===r.label?1:0.5,transition:'var(--t-hover)',cursor:selectable?'pointer':'default'}">
14
19
  <div style="display:flex;align-items:baseline;gap:8px;padding-bottom:4px">
15
20
  <span style="font-family:var(--font-sans);font-size:var(--text-xs);color:var(--text-body);white-space:nowrap;overflow:hidden;text-overflow:ellipsis">{{ r.label }}</span>
16
21
  <span style="margin-left:auto;font-family:var(--font-sans);font-variant-numeric:tabular-nums;font-size:var(--text-xs);color:var(--text-heading)">{{ valueFormat(r.value) }}</span>
@@ -8,6 +8,8 @@ export interface Ribbon3DProps {
8
8
  yaw?: number; pitch?: number;
9
9
  /** Band thickness as a fraction of its row, 0–1 */ ribbon?: number;
10
10
  interactive?: boolean;
11
+ /** Formats values in the tooltip and axis (default: grouped number). */
12
+ valueFormat?: (v: number) => string;
11
13
  style?: React.CSSProperties;
12
14
  }
13
15
  export declare function Ribbon3D(props: Ribbon3DProps): JSX.Element;
@@ -7,6 +7,10 @@ export interface Scatter3DProps {
7
7
  yaw?: number; pitch?: number;
8
8
  /** Base dot radius */ r?: number;
9
9
  legend?: boolean; interactive?: boolean;
10
+ /** Axis titles (default "x" / "y" / "z"). */
11
+ xLabel?: string; yLabel?: string; zLabel?: string;
12
+ /** Formats values in the tooltip (default: grouped number). */
13
+ valueFormat?: (v: number) => string;
10
14
  style?: React.CSSProperties;
11
15
  }
12
16
  export declare function Scatter3D(props: Scatter3DProps): JSX.Element;
@@ -33,7 +33,12 @@ export function SunburstChart({ data, size = 320, ringWidth, valueFormat = fmtNu
33
33
  return (
34
34
  <div style={{ ...wrapStyle, ...style }}>
35
35
  <div style={{ position: "relative", width: size, height: size }}>
36
- <svg width={size} height={size} role="img">
36
+ <svg width={size} height={size} role="img" aria-label={interactive ? "Sunburst chart — arrow keys move between segments, Enter zooms in, Escape zooms out" : undefined} tabIndex={interactive ? 0 : undefined} onBlur={() => setHover(null)}
37
+ onKeyDown={interactive ? (e) => { const n = segs.length; if (!n) return; const h = hover;
38
+ if (e.key === "ArrowRight" || e.key === "ArrowDown") { e.preventDefault(); setHover(h == null ? 0 : (h + 1) % n); }
39
+ else if (e.key === "ArrowLeft" || e.key === "ArrowUp") { e.preventDefault(); setHover(h == null ? n - 1 : (h - 1 + n) % n); }
40
+ else if ((e.key === "Enter" || e.key === " ") && h != null && segs[h] && segs[h].node.children) { e.preventDefault(); setZoom([...zoom, ...segs[h].path]); setHover(null); }
41
+ else if (e.key === "Escape") { if (zoom.length) setZoom(zoom.slice(0, -1)); setHover(null); } } : undefined}>
37
42
  {segs.map((s, i) => (
38
43
  <path key={i} d={arcPath(size / 2, size / 2, rInner + rw * (s.depth + 1) - 1.5, rInner + rw * s.depth, s.a0 + 0.35, Math.max(s.a0 + 0.5, s.a1 - 0.35))}
39
44
  fill={seriesColor(s.colorIdx)} opacity={hover == null ? 0.92 - s.depth * 0.16 : hover === i ? 1 : 0.28}
@@ -33,11 +33,17 @@ const tip = computed(()=>{
33
33
  const p = polar(props.size/2, props.size/2, g.value.rInner+g.value.rw*(s.depth+0.5), (s.a0+s.a1)/2)
34
34
  return { x:p[0], y:p[1], title:s.node.label, value: props.valueFormat(s.node.value)+' · '+((s.node.value/(g.value.focus.value||1))*100).toFixed(1)+'%' }
35
35
  })
36
+ // One Tab stop for the whole chart: arrows walk the segments (same highlight + tooltip as hover), Enter zooms in, Escape zooms out.
37
+ function onKey(e) { if (!props.interactive) return; const segs = g.value.segs, n = segs.length; if (!n) return; const h = hover.value
38
+ if (e.key === 'ArrowRight' || e.key === 'ArrowDown') { e.preventDefault(); hover.value = h == null ? 0 : (h + 1) % n }
39
+ else if (e.key === 'ArrowLeft' || e.key === 'ArrowUp') { e.preventDefault(); hover.value = h == null ? n - 1 : (h - 1 + n) % n }
40
+ else if ((e.key === 'Enter' || e.key === ' ') && h != null && segs[h] && segs[h].node.children) { e.preventDefault(); zoom.value = [...zoom.value, ...segs[h].path]; hover.value = null }
41
+ else if (e.key === 'Escape') { if (zoom.value.length) zoom.value = zoom.value.slice(0, -1); hover.value = null } }
36
42
  </script>
37
43
  <template>
38
44
  <div :style="{position:'relative',display:'inline-block',lineHeight:0,...style}">
39
45
  <div :style="{position:'relative',width:size+'px',height:size+'px'}">
40
- <svg :width="size" :height="size" role="img">
46
+ <svg :width="size" :height="size" role="img" :aria-label="interactive ? 'Sunburst chart — arrow keys move between segments, Enter zooms in, Escape zooms out' : undefined" :tabindex="interactive ? 0 : undefined" @keydown="onKey" @blur="hover = null">
41
47
  <path v-for="(s,i) in g.segs" :key="i" :d="s.d" :fill="s.color"
42
48
  :opacity="hover==null ? 0.92-s.depth*0.16 : (hover===i?1:0.28)"
43
49
  @mouseenter="interactive && (hover=i)" @mouseleave="interactive && (hover=null)"
@@ -8,6 +8,8 @@ export interface Surface3DProps {
8
8
  /** Cell outlines */ wire?: boolean;
9
9
  /** Drag-to-orbit */ interactive?: boolean;
10
10
  valueFormat?: (v: number) => string;
11
+ /** Axis titles (default "x" / "y"). */
12
+ xLabel?: string; yLabel?: string;
11
13
  style?: React.CSSProperties;
12
14
  }
13
15
  export declare function Surface3D(props: Surface3DProps): JSX.Element;
@@ -80,7 +80,12 @@ export function WorldMap({ values = {}, width = 660, height = 340, projection =
80
80
  const h = hover != null ? paths[hover] : null;
81
81
  return (
82
82
  <div style={{ ...wrapStyle, ...style }}>
83
- <svg width={width} height={height - (legend ? 22 : 0)} role="img">
83
+ <svg width={width} height={height - (legend ? 22 : 0)} role="img" aria-label={interactive ? "Map — arrow keys move between regions" + (onSelect ? ", Enter selects" : "") : undefined} tabIndex={interactive ? 0 : undefined} onBlur={() => setHover(null)}
84
+ onKeyDown={interactive ? (e) => { const n = paths.length; if (!n) return; const h = hover;
85
+ if (e.key === "ArrowRight" || e.key === "ArrowDown") { e.preventDefault(); setHover(h == null ? 0 : (h + 1) % n); }
86
+ else if (e.key === "ArrowLeft" || e.key === "ArrowUp") { e.preventDefault(); setHover(h == null ? n - 1 : (h - 1 + n) % n); }
87
+ else if ((e.key === "Enter" || e.key === " ") && h != null && onSelect) { e.preventDefault(); onSelect(paths[h].name, resolved[paths[h].name]); }
88
+ else if (e.key === "Escape") setHover(null); } : undefined}>
84
89
  {paths.map((p, i) => (
85
90
  <path key={p.name + i} d={p.d} fill={fillOf(p.name)} stroke="var(--bg-surface)" strokeWidth="0.5"
86
91
  onMouseEnter={interactive ? () => setHover(i) : undefined} onMouseLeave={interactive ? () => setHover(null) : undefined}
@@ -49,12 +49,18 @@ function fill(name){
49
49
  const swatches = computed(() => props.scale==='diverging'
50
50
  ? ['var(--chart-neg)','color-mix(in srgb, var(--chart-neg) 40%, var(--bg-surface))','var(--chart-track)','color-mix(in srgb, var(--chart-pos) 40%, var(--bg-surface))','var(--chart-pos)']
51
51
  : HEAT)
52
+ // One Tab stop for the whole map: arrows walk the regions (same highlight + tooltip as hover), Enter emits select, Escape clears.
53
+ function onKey(e) { if (!props.interactive) return; const ps = paths.value, n = ps.length; if (!n) return; const h = hover.value
54
+ if (e.key === 'ArrowRight' || e.key === 'ArrowDown') { e.preventDefault(); hover.value = h == null ? 0 : (h + 1) % n }
55
+ else if (e.key === 'ArrowLeft' || e.key === 'ArrowUp') { e.preventDefault(); hover.value = h == null ? n - 1 : (h - 1 + n) % n }
56
+ else if ((e.key === 'Enter' || e.key === ' ') && h != null) { e.preventDefault(); emit('select', ps[h].name, resolved.value[ps[h].name]) }
57
+ else if (e.key === 'Escape') hover.value = null }
52
58
  </script>
53
59
  <template>
54
60
  <div v-if="err" :style="{width:width+'px',height:height+'px',display:'flex',alignItems:'center',justifyContent:'center',fontFamily: 'var(--font-sans)', fontVariantNumeric: 'tabular-nums',fontSize:'var(--text-xs)',color:'var(--text-muted)',background:'var(--bg-inset)',borderRadius:'var(--radius-lg)',...style}">{{ err }}</div>
55
61
  <div v-else-if="!paths" :style="{width:width+'px',height:height+'px',display:'flex',alignItems:'center',justifyContent:'center',fontFamily: 'var(--font-sans)', fontVariantNumeric: 'tabular-nums',fontSize:'var(--text-xs)',color:'var(--text-muted)',...style}">loading map…</div>
56
62
  <div v-else :style="{position:'relative',display:'inline-block',lineHeight:0,...style}">
57
- <svg :width="width" :height="plotH" role="img">
63
+ <svg :width="width" :height="plotH" role="img" :aria-label="interactive ? 'Map — arrow keys move between regions, Enter selects' : undefined" :tabindex="interactive ? 0 : undefined" @keydown="onKey" @blur="hover = null">
58
64
  <path v-for="(p,i) in paths" :key="p.name+i" :d="p.d" :fill="fill(p.name)" stroke="var(--bg-surface)" stroke-width="0.5"
59
65
  @mouseenter="interactive && (hover=i)" @mouseleave="interactive && (hover=null)" @click="emit('select', p.name, resolved[p.name])"
60
66
  :style="{opacity:hover==null||hover===i?1:0.75,transition:'opacity var(--dur-fast) var(--ease-out)'}"/>
@@ -1,13 +1,16 @@
1
1
  import * as React from "react";
2
- /** Expandable list row (Workflow groups): chevron, 32px hairline icon tile, 13px/500 title, 12px meta, right count. */
2
+ /** Expandable list row (Workflow groups): chevron, 32px hairline icon tile, 14px/500 title, 12px meta, right count.
3
+ * The chevron shows only when the row has children to expand. The row is a button only with onClick: focusable, Enter / Space, aria-expanded,
4
+ * hover wash from tokens/hover.css. Without onClick the row is static (no pointer, no hover). Title and meta truncate; expanded content aligns under the title. */
3
5
  export interface ListRowProps {
4
6
  icon?: string;
5
7
  title?: string;
6
8
  meta?: string;
7
- /** Right-aligned text ("1 item") */
9
+ /** Right-aligned text ("1 item"); 0 is shown. */
8
10
  trailing?: React.ReactNode;
9
11
  expanded?: boolean;
10
- onClick?: () => void;
12
+ /** Makes the row a button (toggle expanded here). */
13
+ onClick?: (e: React.SyntheticEvent) => void;
11
14
  children?: React.ReactNode;
12
15
  style?: React.CSSProperties;
13
16
  }