kumo-svelte 0.2.0 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (150) hide show
  1. package/ai/component-registry.json +126 -11
  2. package/ai/component-registry.md +9 -1
  3. package/dist/components/button/Button.svelte +52 -15
  4. package/dist/components/button/Button.svelte.d.ts +6 -6
  5. package/dist/components/chart/ChartLegend.svelte +46 -3
  6. package/dist/components/chart/ChartLegend.svelte.d.ts +5 -0
  7. package/dist/components/chart/TimeseriesChart.svelte +22 -1
  8. package/dist/components/chart/TimeseriesChart.svelte.d.ts +4 -1
  9. package/dist/components/dialog/Dialog.svelte +1 -1
  10. package/dist/components/radio/Radio.svelte +1 -1
  11. package/dist/components/radio/Radio.svelte.d.ts +1 -1
  12. package/dist/components/radio/RadioGroup.svelte +38 -9
  13. package/dist/components/radio/RadioGroup.svelte.d.ts +27 -6
  14. package/dist/components/radio/RadioItem.svelte +7 -5
  15. package/dist/components/radio/RadioItem.svelte.d.ts +25 -4
  16. package/dist/components/radio/RadioTypedValueTestHost.svelte +14 -0
  17. package/dist/components/radio/RadioTypedValueTestHost.svelte.d.ts +3 -0
  18. package/dist/components/radio/index.d.ts +2 -0
  19. package/dist/components/radio/radio.test.d.ts +1 -0
  20. package/dist/components/radio/radio.test.js +11 -0
  21. package/dist/components/sidebar/SidebarContent.svelte +1 -1
  22. package/dist/components/sidebar/SidebarGroupLabel.svelte +1 -1
  23. package/dist/components/toolbar/Toolbar.svelte +68 -0
  24. package/dist/components/toolbar/Toolbar.svelte.d.ts +12 -0
  25. package/dist/components/toolbar/ToolbarButton.svelte +46 -0
  26. package/dist/components/toolbar/ToolbarButton.svelte.d.ts +14 -0
  27. package/dist/components/toolbar/ToolbarInput.svelte +18 -0
  28. package/dist/components/toolbar/ToolbarInput.svelte.d.ts +9 -0
  29. package/dist/components/toolbar/ToolbarInputGroup.svelte +20 -0
  30. package/dist/components/toolbar/ToolbarInputGroup.svelte.d.ts +9 -0
  31. package/dist/components/toolbar/ToolbarTestHost.svelte +36 -0
  32. package/dist/components/toolbar/ToolbarTestHost.svelte.d.ts +18 -0
  33. package/dist/components/toolbar/context.d.ts +30 -0
  34. package/dist/components/toolbar/context.js +35 -0
  35. package/dist/components/toolbar/index.d.ts +16 -0
  36. package/dist/components/toolbar/index.js +12 -0
  37. package/dist/components/toolbar/toolbar.test.d.ts +1 -0
  38. package/dist/components/toolbar/toolbar.test.js +58 -0
  39. package/dist/docs/HomeGrid.svelte +28 -0
  40. package/dist/docs/MdxPage.svelte +7 -3
  41. package/dist/docs/PropsTable.svelte +3 -1
  42. package/dist/docs/PropsTable.svelte.d.ts +1 -0
  43. package/dist/docs/demo-snippets/BadgeColorVariantsDemo.svelte +1 -0
  44. package/dist/docs/demo-snippets/CategoricalColorsDemo.svelte +4 -4
  45. package/dist/docs/demo-snippets/CategoricalCvdDemo.svelte +4 -4
  46. package/dist/docs/demo-snippets/ChartColorSystemsDemo.svelte +2 -2
  47. package/dist/docs/demo-snippets/DialogMaxWidthDemo.svelte +14 -0
  48. package/dist/docs/demo-snippets/DialogMaxWidthDemo.svelte.d.ts +18 -0
  49. package/dist/docs/demo-snippets/DialogWithSelectDemo.svelte +21 -5
  50. package/dist/docs/demo-snippets/LegendHighlightDemo.svelte +105 -0
  51. package/dist/docs/demo-snippets/LegendHighlightDemo.svelte.d.ts +3 -0
  52. package/dist/docs/demo-snippets/LegendOnClickDemo.svelte +118 -0
  53. package/dist/docs/demo-snippets/LegendOnClickDemo.svelte.d.ts +3 -0
  54. package/dist/docs/demo-snippets/RadioTypedValueDemo.svelte +26 -0
  55. package/dist/docs/demo-snippets/RadioTypedValueDemo.svelte.d.ts +3 -0
  56. package/dist/docs/demo-snippets/SemanticColorsDemo.svelte +4 -4
  57. package/dist/docs/demo-snippets/SequentialColorsDemo.svelte +3 -3
  58. package/dist/docs/demo-snippets/ToolbarActionsDemo.svelte +9 -0
  59. package/dist/docs/demo-snippets/ToolbarActionsDemo.svelte.d.ts +18 -0
  60. package/dist/docs/demo-snippets/ToolbarDemo.svelte +15 -0
  61. package/dist/docs/demo-snippets/ToolbarDemo.svelte.d.ts +18 -0
  62. package/dist/docs/demo-snippets/ToolbarInputGroupDemo.svelte +11 -0
  63. package/dist/docs/demo-snippets/ToolbarInputGroupDemo.svelte.d.ts +18 -0
  64. package/dist/docs/demo-snippets/ToolbarLabelsDemo.svelte +9 -0
  65. package/dist/docs/demo-snippets/ToolbarLabelsDemo.svelte.d.ts +18 -0
  66. package/dist/docs/demo-snippets/ToolbarMixedControlsDemo.svelte +10 -0
  67. package/dist/docs/demo-snippets/ToolbarMixedControlsDemo.svelte.d.ts +18 -0
  68. package/dist/docs/demo-snippets/ToolbarSizesDemo.svelte +17 -0
  69. package/dist/docs/demo-snippets/ToolbarSizesDemo.svelte.d.ts +18 -0
  70. package/dist/docs/nav.js +1 -0
  71. package/dist/docs/props-data/ChartLegend.js +50 -26
  72. package/dist/docs/props-data/Radio.js +1 -1
  73. package/dist/docs/props-data/Radio__Group.js +3 -3
  74. package/dist/docs/props-data/Radio__Item.js +1 -1
  75. package/dist/docs/props-data/TimeseriesChart.js +106 -99
  76. package/dist/docs/props-data/Toolbar.d.ts +20 -0
  77. package/dist/docs/props-data/Toolbar.js +19 -0
  78. package/dist/docs/props-data/Toolbar__Button.d.ts +6 -0
  79. package/dist/docs/props-data/Toolbar__Button.js +27 -0
  80. package/dist/docs/props-data/Toolbar__Input.d.ts +6 -0
  81. package/dist/docs/props-data/Toolbar__Input.js +17 -0
  82. package/dist/docs/props-data/Toolbar__InputGroup.d.ts +12 -0
  83. package/dist/docs/props-data/Toolbar__InputGroup.js +13 -0
  84. package/dist/index.d.ts +3 -1
  85. package/dist/index.js +1 -0
  86. package/dist/styles.css +2 -2
  87. package/package.json +16 -16
  88. package/src/lib/components/button/Button.svelte +52 -15
  89. package/src/lib/components/chart/ChartLegend.svelte +46 -3
  90. package/src/lib/components/chart/TimeseriesChart.svelte +22 -1
  91. package/src/lib/components/dialog/Dialog.svelte +1 -1
  92. package/src/lib/components/radio/Radio.svelte +1 -1
  93. package/src/lib/components/radio/RadioGroup.svelte +38 -9
  94. package/src/lib/components/radio/RadioItem.svelte +7 -5
  95. package/src/lib/components/radio/RadioTypedValueTestHost.svelte +14 -0
  96. package/src/lib/components/radio/index.ts +7 -1
  97. package/src/lib/components/radio/radio.test.ts +14 -0
  98. package/src/lib/components/sidebar/SidebarContent.svelte +1 -1
  99. package/src/lib/components/sidebar/SidebarGroupLabel.svelte +1 -1
  100. package/src/lib/components/toolbar/Toolbar.svelte +68 -0
  101. package/src/lib/components/toolbar/ToolbarButton.svelte +46 -0
  102. package/src/lib/components/toolbar/ToolbarInput.svelte +18 -0
  103. package/src/lib/components/toolbar/ToolbarInputGroup.svelte +20 -0
  104. package/src/lib/components/toolbar/ToolbarTestHost.svelte +36 -0
  105. package/src/lib/components/toolbar/context.ts +54 -0
  106. package/src/lib/components/toolbar/index.ts +34 -0
  107. package/src/lib/components/toolbar/toolbar.test.ts +80 -0
  108. package/src/lib/docs/HomeGrid.svelte +28 -0
  109. package/src/lib/docs/MdxPage.svelte +7 -3
  110. package/src/lib/docs/PropsTable.svelte +3 -1
  111. package/src/lib/docs/demo-snippets/BadgeColorVariantsDemo.svelte +1 -0
  112. package/src/lib/docs/demo-snippets/CategoricalColorsDemo.svelte +4 -4
  113. package/src/lib/docs/demo-snippets/CategoricalCvdDemo.svelte +4 -4
  114. package/src/lib/docs/demo-snippets/ChartColorSystemsDemo.svelte +2 -2
  115. package/src/lib/docs/demo-snippets/DialogMaxWidthDemo.svelte +14 -0
  116. package/src/lib/docs/demo-snippets/DialogWithSelectDemo.svelte +21 -5
  117. package/src/lib/docs/demo-snippets/LegendHighlightDemo.svelte +105 -0
  118. package/src/lib/docs/demo-snippets/LegendOnClickDemo.svelte +118 -0
  119. package/src/lib/docs/demo-snippets/RadioTypedValueDemo.svelte +26 -0
  120. package/src/lib/docs/demo-snippets/SemanticColorsDemo.svelte +4 -4
  121. package/src/lib/docs/demo-snippets/SequentialColorsDemo.svelte +3 -3
  122. package/src/lib/docs/demo-snippets/ToolbarActionsDemo.svelte +9 -0
  123. package/src/lib/docs/demo-snippets/ToolbarDemo.svelte +15 -0
  124. package/src/lib/docs/demo-snippets/ToolbarInputGroupDemo.svelte +11 -0
  125. package/src/lib/docs/demo-snippets/ToolbarLabelsDemo.svelte +9 -0
  126. package/src/lib/docs/demo-snippets/ToolbarMixedControlsDemo.svelte +10 -0
  127. package/src/lib/docs/demo-snippets/ToolbarSizesDemo.svelte +17 -0
  128. package/src/lib/docs/nav.ts +1 -0
  129. package/src/lib/docs/props-data/ChartLegend.ts +55 -26
  130. package/src/lib/docs/props-data/Radio.ts +1 -1
  131. package/src/lib/docs/props-data/Radio__Group.ts +3 -3
  132. package/src/lib/docs/props-data/Radio__Item.ts +1 -1
  133. package/src/lib/docs/props-data/TimeseriesChart.ts +118 -99
  134. package/src/lib/docs/props-data/Toolbar.ts +19 -0
  135. package/src/lib/docs/props-data/Toolbar__Button.ts +27 -0
  136. package/src/lib/docs/props-data/Toolbar__Input.ts +17 -0
  137. package/src/lib/docs/props-data/Toolbar__InputGroup.ts +13 -0
  138. package/src/lib/index.ts +97 -14
  139. package/src/lib/styles.css +9 -5
  140. package/src/routes/charts/colors/+page.md +1 -0
  141. package/src/routes/charts/timeseries/+page.md +43 -21
  142. package/src/routes/components/dialog/+page.md +6 -0
  143. package/src/routes/components/radio/+page.md +7 -0
  144. package/src/routes/components/toolbar/+page.md +133 -0
  145. package/src/blocks/delete-resource/delete-resource.svelte.d.ts +0 -32
  146. package/src/blocks/delete-resource/index.d.ts +0 -2
  147. package/src/blocks/page-header/index.d.ts +0 -2
  148. package/src/blocks/page-header/page-header.svelte.d.ts +0 -46
  149. package/src/blocks/resource-list/index.d.ts +0 -1
  150. package/src/blocks/resource-list/resource-list.svelte.d.ts +0 -13
@@ -1,5 +1,5 @@
1
1
  {
2
- "version": "0.2.0",
2
+ "version": "0.3.0",
3
3
  "components": {
4
4
  "Autocomplete": {
5
5
  "name": "Autocomplete",
@@ -608,15 +608,14 @@
608
608
  },
609
609
  "colors": [
610
610
  "bg-kumo-base",
611
- "bg-kumo-brand",
612
- "bg-kumo-brand-hover",
613
- "bg-kumo-danger",
614
611
  "bg-kumo-tint",
615
612
  "ring-kumo-brand",
613
+ "ring-kumo-danger",
616
614
  "ring-kumo-focus",
617
- "ring-kumo-hairline",
615
+ "ring-kumo-line",
618
616
  "text-kumo-danger",
619
617
  "text-kumo-default",
618
+ "text-kumo-strong",
620
619
  "text-kumo-subtle"
621
620
  ],
622
621
  "subComponents": {
@@ -3569,7 +3568,7 @@
3569
3568
  "description": "Additional classes merged onto the root element."
3570
3569
  },
3571
3570
  "onValueChange": {
3572
- "type": "(value: string) => void",
3571
+ "type": "(value: string, eventDetails?: unknown) => void",
3573
3572
  "optional": true,
3574
3573
  "description": "Called when the value changes."
3575
3574
  }
@@ -3635,7 +3634,7 @@
3635
3634
  "description": "Supporting description text."
3636
3635
  },
3637
3636
  "value": {
3638
- "type": "string",
3637
+ "type": "Value",
3639
3638
  "optional": true,
3640
3639
  "description": "Controlled value."
3641
3640
  },
@@ -3665,7 +3664,7 @@
3665
3664
  "description": "Additional classes merged onto the root element."
3666
3665
  },
3667
3666
  "defaultValue": {
3668
- "type": "string",
3667
+ "type": "Value",
3669
3668
  "optional": true,
3670
3669
  "description": "Initial uncontrolled value."
3671
3670
  },
@@ -3675,7 +3674,7 @@
3675
3674
  "description": "Marks the field as required."
3676
3675
  },
3677
3676
  "onValueChange": {
3678
- "type": "(value: string) => void",
3677
+ "type": "(value: Value, eventDetails?: unknown) => void",
3679
3678
  "optional": true,
3680
3679
  "description": "Called when the value changes."
3681
3680
  }
@@ -3731,7 +3730,7 @@
3731
3730
  "description": "Supporting description text."
3732
3731
  },
3733
3732
  "value": {
3734
- "type": "string",
3733
+ "type": "Value",
3735
3734
  "optional": false,
3736
3735
  "required": true,
3737
3736
  "description": "Controlled value."
@@ -5189,6 +5188,119 @@
5189
5188
  "props": {},
5190
5189
  "colors": []
5191
5190
  },
5191
+ "Toolbar": {
5192
+ "name": "Toolbar",
5193
+ "type": "component",
5194
+ "category": "Action",
5195
+ "description": "Compose explicit toolbar controls into one clean grouped card.",
5196
+ "importPath": "kumo-svelte/components/toolbar",
5197
+ "sourceFile": "components/toolbar",
5198
+ "props": {
5199
+ "children": {
5200
+ "type": "Snippet",
5201
+ "optional": false,
5202
+ "required": true,
5203
+ "description": "Toolbar controls rendered as one grouped card."
5204
+ },
5205
+ "size": {
5206
+ "type": "enum",
5207
+ "optional": true,
5208
+ "values": [
5209
+ "xs",
5210
+ "sm",
5211
+ "base",
5212
+ "lg"
5213
+ ],
5214
+ "default": "base",
5215
+ "description": "Locks every supported toolbar item to this size."
5216
+ },
5217
+ "class": {
5218
+ "type": "string",
5219
+ "optional": true,
5220
+ "description": "Additional classes merged onto the toolbar root."
5221
+ }
5222
+ },
5223
+ "colors": [
5224
+ "bg-kumo-control",
5225
+ "border-kumo-line",
5226
+ "ring-kumo-brand",
5227
+ "ring-kumo-focus",
5228
+ "ring-kumo-line"
5229
+ ],
5230
+ "subComponents": {
5231
+ "Button": {
5232
+ "description": "Toolbar.Button",
5233
+ "props": {
5234
+ "children": {
5235
+ "type": "Snippet",
5236
+ "optional": true,
5237
+ "description": "Optional visible button label."
5238
+ },
5239
+ "icon": {
5240
+ "type": "Component",
5241
+ "optional": true,
5242
+ "description": "Optional icon component rendered before the label."
5243
+ },
5244
+ "shape": {
5245
+ "type": "enum",
5246
+ "optional": true,
5247
+ "values": [
5248
+ "base",
5249
+ "square",
5250
+ "circle"
5251
+ ],
5252
+ "description": "Button shape. Icon-only toolbar buttons default to square."
5253
+ },
5254
+ "disabled": {
5255
+ "type": "boolean",
5256
+ "optional": true,
5257
+ "description": "Disables the toolbar button."
5258
+ },
5259
+ "loading": {
5260
+ "type": "boolean",
5261
+ "optional": true,
5262
+ "description": "Shows a loading indicator and disables the toolbar button."
5263
+ }
5264
+ }
5265
+ },
5266
+ "Input": {
5267
+ "description": "Toolbar.Input",
5268
+ "props": {
5269
+ "value": {
5270
+ "type": "string | number",
5271
+ "optional": true,
5272
+ "description": "Input value, bindable with `bind:value`."
5273
+ },
5274
+ "onValueChange": {
5275
+ "type": "(value: string) => void",
5276
+ "optional": true,
5277
+ "description": "Called when the input value changes."
5278
+ },
5279
+ "class": {
5280
+ "type": "string",
5281
+ "optional": true,
5282
+ "description": "Additional classes merged onto the toolbar input."
5283
+ }
5284
+ }
5285
+ },
5286
+ "InputGroup": {
5287
+ "description": "Toolbar.InputGroup",
5288
+ "props": {
5289
+ "children": {
5290
+ "type": "Snippet",
5291
+ "optional": false,
5292
+ "required": true,
5293
+ "description": "InputGroup children rendered as one toolbar item."
5294
+ },
5295
+ "class": {
5296
+ "type": "string",
5297
+ "optional": true,
5298
+ "description": "Additional classes merged onto the toolbar input group."
5299
+ }
5300
+ }
5301
+ }
5302
+ }
5303
+ },
5192
5304
  "Tooltip": {
5193
5305
  "name": "Tooltip",
5194
5306
  "type": "component",
@@ -5362,12 +5474,14 @@
5362
5474
  "Tabs",
5363
5475
  "Text",
5364
5476
  "Toast",
5477
+ "Toolbar",
5365
5478
  "Tooltip"
5366
5479
  ],
5367
5480
  "byCategory": {
5368
5481
  "Action": [
5369
5482
  "Button",
5370
- "Link"
5483
+ "Link",
5484
+ "Toolbar"
5371
5485
  ],
5372
5486
  "Display": [
5373
5487
  "Badge",
@@ -5465,6 +5579,7 @@
5465
5579
  "Tabs",
5466
5580
  "Text",
5467
5581
  "Toast",
5582
+ "Toolbar",
5468
5583
  "Tooltip"
5469
5584
  ],
5470
5585
  "block": [
@@ -1,6 +1,6 @@
1
1
  # Kumo Svelte Component Registry
2
2
 
3
- Version: 0.2.0
3
+ Version: 0.3.0
4
4
 
5
5
  ## Autocomplete
6
6
 
@@ -322,6 +322,14 @@ A notification system for displaying brief, non-intrusive messages to users.
322
322
  - Import: `import { Toast } from "kumo-svelte/components/toast";`
323
323
  - Source: `components/toast`
324
324
 
325
+ ## Toolbar
326
+
327
+ Compose explicit toolbar controls into one clean grouped card.
328
+
329
+ - Category: Action
330
+ - Import: `import { Toolbar } from "kumo-svelte/components/toolbar";`
331
+ - Source: `components/toolbar`
332
+
325
333
  ## Tooltip
326
334
 
327
335
  A popup that displays information related to an element when the element receives keyboard focus or the mouse hovers over it.
@@ -45,12 +45,13 @@
45
45
  },
46
46
  variant: {
47
47
  primary: {
48
- classes: 'bg-kumo-brand !text-white hover:bg-kumo-brand-hover disabled:bg-kumo-brand/50',
48
+ classes:
49
+ 'relative overflow-hidden bg-(--kumo-button-emphasis-bg) !text-white ring ring-(--kumo-button-emphasis-ring) disabled:opacity-50',
49
50
  description: 'High-emphasis button for primary actions'
50
51
  },
51
52
  secondary: {
52
53
  classes:
53
- 'bg-kumo-base !text-kumo-default ring not-disabled:hover:bg-kumo-tint disabled:bg-kumo-base/50 disabled:!text-kumo-default/70 ring-kumo-hairline data-[state=open]:bg-kumo-base',
54
+ 'bg-kumo-base !text-kumo-default ring not-disabled:hover:bg-kumo-tint disabled:bg-kumo-base/50 disabled:!text-kumo-default/70 ring-kumo-line data-[state=open]:bg-kumo-base',
54
55
  description: 'Default button style for most actions'
55
56
  },
56
57
  ghost: {
@@ -58,16 +59,18 @@
58
59
  description: 'Minimal button with no background'
59
60
  },
60
61
  destructive: {
61
- classes: 'bg-kumo-danger !text-white hover:bg-kumo-danger/70',
62
+ classes:
63
+ 'relative overflow-hidden bg-(--kumo-button-emphasis-bg) !text-white ring ring-(--kumo-button-emphasis-ring) disabled:opacity-50',
62
64
  description: 'Danger button for destructive actions like delete'
63
65
  },
64
66
  'secondary-destructive': {
65
67
  classes:
66
- 'bg-kumo-base !text-kumo-danger ring not-disabled:hover:bg-kumo-base disabled:bg-kumo-base/50 disabled:!text-kumo-danger/70 ring-kumo-hairline data-[state=open]:bg-kumo-base',
68
+ 'bg-kumo-base !text-kumo-danger ring not-disabled:hover:!text-kumo-danger not-disabled:hover:ring-kumo-danger/30 disabled:bg-kumo-base/50 disabled:!text-kumo-danger/70 ring-kumo-line data-[state=open]:bg-kumo-base',
67
69
  description: 'Secondary button with destructive text for less prominent dangerous actions'
68
70
  },
69
71
  outline: {
70
- classes: 'bg-transparent text-kumo-default ring ring-kumo-hairline',
72
+ classes:
73
+ 'bg-transparent text-kumo-default ring ring-kumo-line transition-colors not-disabled:hover:text-kumo-strong not-disabled:hover:ring-kumo-focus/25',
71
74
  description: 'Bordered button with transparent background'
72
75
  }
73
76
  }
@@ -100,10 +103,10 @@
100
103
  'focus:outline-none focus:ring-kumo-focus/50 focus-visible:ring-2 focus-visible:ring-kumo-brand',
101
104
  'cursor-pointer',
102
105
  'disabled:cursor-not-allowed disabled:text-kumo-subtle',
103
- KUMO_BUTTON_VARIANTS.variant[variant].classes,
104
106
  KUMO_BUTTON_VARIANTS.size[size].classes,
105
107
  KUMO_BUTTON_VARIANTS.shape[shape].classes,
106
- isCompactShape && KUMO_BUTTON_VARIANTS.compactSize[size].classes
108
+ isCompactShape && KUMO_BUTTON_VARIANTS.compactSize[size].classes,
109
+ KUMO_BUTTON_VARIANTS.variant[variant].classes
107
110
  );
108
111
  }
109
112
 
@@ -120,7 +123,7 @@
120
123
  variant?: Variant;
121
124
  loading?: boolean;
122
125
  title?: string;
123
- componentName?: 'Button' | 'LinkButton';
126
+ componentName?: 'Button' | 'LinkButton' | 'Toolbar.Button';
124
127
  [key: string]: unknown;
125
128
  }
126
129
 
@@ -152,6 +155,19 @@
152
155
 
153
156
  const loaderSize = $derived(size === 'lg' ? 16 : 14);
154
157
  const externalProps = $derived(external ? { target: '_blank', rel: 'noopener noreferrer' } : {});
158
+ const emphasisToken = $derived(
159
+ variant === 'primary'
160
+ ? 'var(--color-kumo-brand)'
161
+ : variant === 'destructive'
162
+ ? 'var(--color-kumo-danger)'
163
+ : undefined
164
+ );
165
+ const emphasisRing = $derived(emphasisToken ? `color-mix(in oklch, ${emphasisToken}, black 10%)` : undefined);
166
+ const emphasisBg = $derived(emphasisToken ? `color-mix(in oklch, ${emphasisToken}, white 30%)` : undefined);
167
+ const emphasisGradientStart = $derived(
168
+ emphasisToken ? `color-mix(in oklch, ${emphasisToken}, white 15%)` : undefined
169
+ );
170
+ const emphasisGradientEnd = $derived(emphasisToken);
155
171
  </script>
156
172
 
157
173
  {#snippet buttonElement()}
@@ -164,16 +180,37 @@
164
180
  aria-busy={loading || undefined}
165
181
  data-kumo-component={componentName}
166
182
  data-kumo-part={href ? 'link-button' : 'button'}
183
+ style:--kumo-button-emphasis-ring={emphasisRing}
184
+ style:--kumo-button-emphasis-bg={emphasisBg}
185
+ style:--kumo-button-emphasis-gradient-start={emphasisGradientStart}
186
+ style:--kumo-button-emphasis-gradient-end={emphasisGradientEnd}
167
187
  {...externalProps}
168
188
  {...rest}
169
189
  >
170
- {#if loading}
171
- <Loader size={loaderSize} />
172
- {:else if IconComponent}
173
- <IconComponent />
174
- {/if}
175
- {#if children}
176
- <span class="contents">{@render children()}</span>
190
+ {#if emphasisToken}
191
+ <span
192
+ aria-hidden="true"
193
+ class="absolute inset-0 translate-y-px rounded-[inherit] bg-linear-to-b from-(--kumo-button-emphasis-gradient-start) to-(--kumo-button-emphasis-gradient-end) group-hover:from-(--kumo-button-emphasis-bg)"
194
+ ></span>
195
+ <span class="relative flex items-center gap-1.5">
196
+ {#if loading}
197
+ <Loader size={loaderSize} />
198
+ {:else if IconComponent}
199
+ <IconComponent />
200
+ {/if}
201
+ {#if children}
202
+ <span class="contents">{@render children()}</span>
203
+ {/if}
204
+ </span>
205
+ {:else}
206
+ {#if loading}
207
+ <Loader size={loaderSize} />
208
+ {:else if IconComponent}
209
+ <IconComponent />
210
+ {/if}
211
+ {#if children}
212
+ <span class="contents">{@render children()}</span>
213
+ {/if}
177
214
  {/if}
178
215
  </svelte:element>
179
216
  {/snippet}
@@ -13,7 +13,7 @@ declare const Button: Component<{
13
13
  variant?: "secondary" | "primary" | "ghost" | "destructive" | "secondary-destructive" | "outline";
14
14
  loading?: boolean;
15
15
  title?: string;
16
- componentName?: "Button" | "LinkButton";
16
+ componentName?: "Button" | "LinkButton" | "Toolbar.Button";
17
17
  }, {
18
18
  KUMO_BUTTON_VARIANTS: {
19
19
  readonly shape: {
@@ -64,11 +64,11 @@ declare const Button: Component<{
64
64
  };
65
65
  readonly variant: {
66
66
  readonly primary: {
67
- readonly classes: "bg-kumo-brand !text-white hover:bg-kumo-brand-hover disabled:bg-kumo-brand/50";
67
+ readonly classes: "relative overflow-hidden bg-(--kumo-button-emphasis-bg) !text-white ring ring-(--kumo-button-emphasis-ring) disabled:opacity-50";
68
68
  readonly description: "High-emphasis button for primary actions";
69
69
  };
70
70
  readonly secondary: {
71
- readonly classes: "bg-kumo-base !text-kumo-default ring not-disabled:hover:bg-kumo-tint disabled:bg-kumo-base/50 disabled:!text-kumo-default/70 ring-kumo-hairline data-[state=open]:bg-kumo-base";
71
+ readonly classes: "bg-kumo-base !text-kumo-default ring not-disabled:hover:bg-kumo-tint disabled:bg-kumo-base/50 disabled:!text-kumo-default/70 ring-kumo-line data-[state=open]:bg-kumo-base";
72
72
  readonly description: "Default button style for most actions";
73
73
  };
74
74
  readonly ghost: {
@@ -76,15 +76,15 @@ declare const Button: Component<{
76
76
  readonly description: "Minimal button with no background";
77
77
  };
78
78
  readonly destructive: {
79
- readonly classes: "bg-kumo-danger !text-white hover:bg-kumo-danger/70";
79
+ readonly classes: "relative overflow-hidden bg-(--kumo-button-emphasis-bg) !text-white ring ring-(--kumo-button-emphasis-ring) disabled:opacity-50";
80
80
  readonly description: "Danger button for destructive actions like delete";
81
81
  };
82
82
  readonly 'secondary-destructive': {
83
- readonly classes: "bg-kumo-base !text-kumo-danger ring not-disabled:hover:bg-kumo-base disabled:bg-kumo-base/50 disabled:!text-kumo-danger/70 ring-kumo-hairline data-[state=open]:bg-kumo-base";
83
+ readonly classes: "bg-kumo-base !text-kumo-danger ring not-disabled:hover:!text-kumo-danger not-disabled:hover:ring-kumo-danger/30 disabled:bg-kumo-base/50 disabled:!text-kumo-danger/70 ring-kumo-line data-[state=open]:bg-kumo-base";
84
84
  readonly description: "Secondary button with destructive text for less prominent dangerous actions";
85
85
  };
86
86
  readonly outline: {
87
- readonly classes: "bg-transparent text-kumo-default ring ring-kumo-hairline";
87
+ readonly classes: "bg-transparent text-kumo-default ring ring-kumo-line transition-colors not-disabled:hover:text-kumo-strong not-disabled:hover:ring-kumo-focus/25";
88
88
  readonly description: "Bordered button with transparent background";
89
89
  };
90
90
  };
@@ -8,13 +8,47 @@
8
8
  value: string;
9
9
  unit?: string;
10
10
  inactive?: boolean;
11
+ onpointerenter?: (event: PointerEvent) => void;
12
+ onpointerleave?: (event: PointerEvent) => void;
13
+ onclick?: (event: MouseEvent) => void;
14
+ class?: string;
15
+ [key: string]: unknown;
11
16
  }
12
17
 
13
- let { variant = 'small', name, color, value, unit, inactive = false }: Props = $props();
18
+ let {
19
+ variant = 'small',
20
+ name,
21
+ color,
22
+ value,
23
+ unit,
24
+ inactive = false,
25
+ onpointerenter,
26
+ onpointerleave,
27
+ onclick,
28
+ class: className,
29
+ ...rest
30
+ }: Props = $props();
31
+
32
+ function handleKeydown(event: KeyboardEvent) {
33
+ if (!onclick || (event.key !== 'Enter' && event.key !== ' ')) return;
34
+ event.preventDefault();
35
+ (event.currentTarget as HTMLElement).dispatchEvent(
36
+ new MouseEvent('click', { bubbles: true, cancelable: true })
37
+ );
38
+ }
14
39
  </script>
15
40
 
16
41
  {#if variant === 'large'}
17
- <div class="inline-flex min-w-42 flex-col gap-2 py-2">
42
+ <div
43
+ role="button"
44
+ tabindex={onclick ? 0 : -1}
45
+ class={cn('inline-flex min-w-42 flex-col gap-2 py-2', onclick && 'cursor-pointer', className)}
46
+ {onpointerenter}
47
+ {onpointerleave}
48
+ {onclick}
49
+ onkeydown={handleKeydown}
50
+ {...rest}
51
+ >
18
52
  <div class="flex items-center gap-2">
19
53
  <span class={cn('inline-block size-2 rounded-full', inactive && 'opacity-50')} style:background-color={color}></span>
20
54
  <span class={cn('text-xs', inactive && 'opacity-50')}>{name}</span>
@@ -25,7 +59,16 @@
25
59
  </div>
26
60
  </div>
27
61
  {:else}
28
- <div class="inline-flex items-center gap-2">
62
+ <div
63
+ role="button"
64
+ tabindex={onclick ? 0 : -1}
65
+ class={cn('inline-flex items-center gap-2', onclick && 'cursor-pointer', className)}
66
+ {onpointerenter}
67
+ {onpointerleave}
68
+ {onclick}
69
+ onkeydown={handleKeydown}
70
+ {...rest}
71
+ >
29
72
  <span class={cn('inline-block size-2 rounded-full', inactive && 'opacity-50')} style:background-color={color}></span>
30
73
  <span class={cn('text-xs', inactive && 'opacity-50')}>{name}</span>
31
74
  <span class={cn('text-xs font-medium', inactive && 'opacity-50')}>{value}</span>
@@ -5,6 +5,11 @@ interface Props {
5
5
  value: string;
6
6
  unit?: string;
7
7
  inactive?: boolean;
8
+ onpointerenter?: (event: PointerEvent) => void;
9
+ onpointerleave?: (event: PointerEvent) => void;
10
+ onclick?: (event: MouseEvent) => void;
11
+ class?: string;
12
+ [key: string]: unknown;
8
13
  }
9
14
  declare const ChartLegend: import("svelte").Component<Props, {}, "">;
10
15
  type ChartLegend = ReturnType<typeof ChartLegend>;
@@ -28,12 +28,14 @@
28
28
  tooltipBoundary?: 'clipping-ancestors' | Element | Element[];
29
29
  tooltipFollowCursor?: 'both' | 'x';
30
30
  incomplete?: { before?: number; after?: number };
31
+ enableLegendSelection?: boolean;
31
32
  height?: number;
32
33
  onTimeRangeChange?: (from: number, to: number) => void;
33
34
  isDarkMode?: boolean;
34
35
  gradient?: boolean;
35
36
  loading?: boolean;
36
37
  ariaDescription?: string;
38
+ chartRef?: EChartsType | null;
37
39
  animation?: boolean;
38
40
  animationDuration?: number;
39
41
  optionUpdateBehavior?: Record<string, unknown>;
@@ -56,22 +58,24 @@
56
58
  tooltipBoundary,
57
59
  tooltipFollowCursor = 'both',
58
60
  incomplete,
61
+ enableLegendSelection = false,
59
62
  height = 350,
60
63
  onTimeRangeChange,
61
64
  isDarkMode,
62
65
  gradient = false,
63
66
  loading = false,
64
67
  ariaDescription,
68
+ chartRef = $bindable(null),
65
69
  animation = true,
66
70
  animationDuration = 600,
67
71
  optionUpdateBehavior
68
72
  }: Props = $props();
69
73
 
70
- let chartRef: EChartsType | null = $state(null);
71
74
  let detectedDarkMode = $state(false);
72
75
  let containerRef: HTMLDivElement;
73
76
  let tooltipAnchor: HTMLSpanElement | null = $state(null);
74
77
  let tooltipState: { ts: number; rows: { name: string; value: number; color: string }[]; hiddenCount: number } | null = $state(null);
78
+ let legendSelected: Record<string, boolean> | null = $state(null);
75
79
  let mousePos = $state({ x: 0, y: 0 });
76
80
  const effectiveDarkMode = $derived(isDarkMode ?? detectedDarkMode);
77
81
 
@@ -207,6 +211,7 @@
207
211
  animationEasing: 'cubicOut',
208
212
  animationEasingUpdate: 'cubicOut',
209
213
  toolbox: { show: false },
214
+ ...(enableLegendSelection ? { legend: { show: false } } : {}),
210
215
  xAxis: {
211
216
  name: xAxisName,
212
217
  nameLocation: 'middle',
@@ -242,6 +247,7 @@
242
247
 
243
248
  for (const series of data) {
244
249
  if (seenNames.has(series.name)) continue;
250
+ if (legendSelected && legendSelected[series.name] === false) continue;
245
251
  seenNames.add(series.name);
246
252
  const value = findNearest(series.data, ts);
247
253
  if (value != null) allRows.push({ name: series.name, value, color: series.color });
@@ -270,6 +276,15 @@
270
276
  globalout: () => {
271
277
  tooltipState = null;
272
278
  },
279
+ legendselectchanged: (params: { selected?: Record<string, boolean> }) => {
280
+ legendSelected = params.selected ?? null;
281
+ },
282
+ legendselected: (params: { selected?: Record<string, boolean> }) => {
283
+ legendSelected = params.selected ?? null;
284
+ },
285
+ legendunselected: (params: { selected?: Record<string, boolean> }) => {
286
+ legendSelected = params.selected ?? null;
287
+ },
273
288
  ...(onTimeRangeChange
274
289
  ? {
275
290
  brushend: (params: any) => {
@@ -283,6 +298,12 @@
283
298
  }
284
299
  );
285
300
 
301
+ $effect(() => {
302
+ enableLegendSelection;
303
+ effectiveDarkMode;
304
+ legendSelected = null;
305
+ });
306
+
286
307
  $effect(() => {
287
308
  if (chartRef && onTimeRangeChange && !loading) {
288
309
  chartRef.dispatchAction({
@@ -1,3 +1,4 @@
1
+ import type { EChartsType } from 'echarts/core';
1
2
  export interface TimeseriesData {
2
3
  name: string;
3
4
  data: [number, number][];
@@ -23,16 +24,18 @@ interface Props {
23
24
  before?: number;
24
25
  after?: number;
25
26
  };
27
+ enableLegendSelection?: boolean;
26
28
  height?: number;
27
29
  onTimeRangeChange?: (from: number, to: number) => void;
28
30
  isDarkMode?: boolean;
29
31
  gradient?: boolean;
30
32
  loading?: boolean;
31
33
  ariaDescription?: string;
34
+ chartRef?: EChartsType | null;
32
35
  animation?: boolean;
33
36
  animationDuration?: number;
34
37
  optionUpdateBehavior?: Record<string, unknown>;
35
38
  }
36
- declare const TimeseriesChart: import("svelte").Component<Props, {}, "">;
39
+ declare const TimeseriesChart: import("svelte").Component<Props, {}, "chartRef">;
37
40
  type TimeseriesChart = ReturnType<typeof TimeseriesChart>;
38
41
  export default TimeseriesChart;
@@ -136,7 +136,7 @@
136
136
 
137
137
  let contentClasses = $derived(
138
138
  cn(
139
- 'shadow-m ring ring-kumo-line fixed top-1/2 left-1/2 w-full sm:w-auto max-w-[calc(100vw-2rem)] sm:max-w-[calc(100vw-3rem)] -translate-x-1/2 -translate-y-1/2 overflow-hidden rounded-xl bg-kumo-base text-kumo-default duration-150 data-ending-style:scale-90 data-ending-style:opacity-0 data-starting-style:scale-90 data-starting-style:opacity-0',
139
+ 'shadow-m ring ring-kumo-line fixed top-1/2 left-1/2 w-full sm:w-auto max-w-[calc(100vw-2rem)] -translate-x-1/2 -translate-y-1/2 overflow-hidden rounded-xl bg-kumo-base text-kumo-default duration-150 data-ending-style:scale-90 data-ending-style:opacity-0 data-starting-style:scale-90 data-starting-style:opacity-0',
140
140
  KUMO_DIALOG_VARIANTS.size[size].classes,
141
141
  className
142
142
  )
@@ -76,7 +76,7 @@
76
76
  description?: string | Snippet;
77
77
  error?: string;
78
78
  class?: string;
79
- onValueChange?: (value: string) => void;
79
+ onValueChange?: (value: string, eventDetails?: unknown) => void;
80
80
  }
81
81
 
82
82
  let {
@@ -56,7 +56,7 @@ interface Props {
56
56
  description?: string | Snippet;
57
57
  error?: string;
58
58
  class?: string;
59
- onValueChange?: (value: string) => void;
59
+ onValueChange?: (value: string, eventDetails?: unknown) => void;
60
60
  }
61
61
  declare const Radio: import("svelte").Component<Props, {}, "value">;
62
62
  type Radio = ReturnType<typeof Radio>;