@redvars/peacock 3.3.1 → 3.3.3

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 (93) hide show
  1. package/dist/{IndividualComponent-tDnXrOLV.js → IndividualComponent-Dt5xirYG.js} +2 -2
  2. package/dist/{IndividualComponent-tDnXrOLV.js.map → IndividualComponent-Dt5xirYG.js.map} +1 -1
  3. package/dist/array-D5vjT2Xm.js +14 -0
  4. package/dist/array-D5vjT2Xm.js.map +1 -0
  5. package/dist/{button-trIfcqC7.js → button-ClzS8JLq.js} +3 -3
  6. package/dist/{button-trIfcqC7.js.map → button-ClzS8JLq.js.map} +1 -1
  7. package/dist/{button-group-DA7xoziD.js → button-group-BMS5WvaF.js} +4 -4
  8. package/dist/{button-group-DA7xoziD.js.map → button-group-BMS5WvaF.js.map} +1 -1
  9. package/dist/button-group.js +4 -4
  10. package/dist/button.js +3 -3
  11. package/dist/card.js +104 -0
  12. package/dist/card.js.map +1 -0
  13. package/dist/chart-bar-DbnXQgvS.js +1121 -0
  14. package/dist/chart-bar-DbnXQgvS.js.map +1 -0
  15. package/dist/chart-bar.js +259 -0
  16. package/dist/chart-bar.js.map +1 -0
  17. package/dist/chart-donut.js +4 -2
  18. package/dist/chart-donut.js.map +1 -1
  19. package/dist/chart-doughnut.js +4 -2
  20. package/dist/chart-doughnut.js.map +1 -1
  21. package/dist/chart-pie.js +4 -2
  22. package/dist/chart-pie.js.map +1 -1
  23. package/dist/chart-stacked-bar.js +401 -0
  24. package/dist/chart-stacked-bar.js.map +1 -0
  25. package/dist/{class-map-hJdvjl-W.js → class-map-59YGWLnx.js} +2 -2
  26. package/dist/{class-map-hJdvjl-W.js.map → class-map-59YGWLnx.js.map} +1 -1
  27. package/dist/clock.js +1 -1
  28. package/dist/code-editor.js +3 -3
  29. package/dist/code-highlighter.js +3 -3
  30. package/dist/custom-elements-jsdocs.json +2308 -766
  31. package/dist/custom-elements.json +3908 -2601
  32. package/dist/index.js +16 -9
  33. package/dist/index.js.map +1 -1
  34. package/dist/number-counter.js +2 -2
  35. package/dist/{observe-theme-change-BISF-Gl5.js → observe-theme-change-pALI5fmV.js} +2 -2
  36. package/dist/{observe-theme-change-BISF-Gl5.js.map → observe-theme-change-pALI5fmV.js.map} +1 -1
  37. package/dist/peacock-loader.js +25 -526
  38. package/dist/peacock-loader.js.map +1 -1
  39. package/dist/pie-Dz0IDiPt.js +537 -0
  40. package/dist/pie-Dz0IDiPt.js.map +1 -0
  41. package/dist/{tree-view-CLolVlU0.js → radio-b70_Ie9n.js} +2216 -901
  42. package/dist/radio-b70_Ie9n.js.map +1 -0
  43. package/dist/src/card/card.d.ts +27 -0
  44. package/dist/src/card/index.d.ts +1 -0
  45. package/dist/src/chart-bar/chart-bar.d.ts +53 -0
  46. package/dist/src/chart-bar/chart-stacked-bar.d.ts +78 -0
  47. package/dist/src/chart-bar/index.d.ts +2 -0
  48. package/dist/src/index.d.ts +6 -0
  49. package/dist/src/menu/menu-item/menu-item.d.ts +1 -1
  50. package/dist/src/radio/index.d.ts +1 -0
  51. package/dist/src/radio/radio.d.ts +73 -0
  52. package/dist/src/snackbar/index.d.ts +1 -0
  53. package/dist/src/snackbar/snackbar.d.ts +40 -0
  54. package/dist/src/tabs/tab-group.d.ts +1 -1
  55. package/dist/src/tabs/tab-panel.d.ts +1 -0
  56. package/dist/src/tabs/tab.d.ts +2 -1
  57. package/dist/{style-map-CfNHEkQp.js → style-map-DcB52w-l.js} +2 -2
  58. package/dist/{style-map-CfNHEkQp.js.map → style-map-DcB52w-l.js.map} +1 -1
  59. package/dist/test/card.test.d.ts +1 -0
  60. package/dist/test/chart-bar.test.d.ts +1 -0
  61. package/dist/test/snackbar.test.d.ts +1 -0
  62. package/dist/{transform-DRuHEvar.js → transform-DSwFSqzD.js} +13 -558
  63. package/dist/transform-DSwFSqzD.js.map +1 -0
  64. package/dist/tsconfig.tsbuildinfo +1 -1
  65. package/dist/{unsafe-html-CV6Je6HL.js → unsafe-html-C2r3PyzF.js} +2 -2
  66. package/dist/{unsafe-html-CV6Je6HL.js.map → unsafe-html-C2r3PyzF.js.map} +1 -1
  67. package/package.json +1 -1
  68. package/readme.md +2 -2
  69. package/src/card/card.scss +61 -0
  70. package/src/card/card.ts +38 -0
  71. package/src/card/index.ts +1 -0
  72. package/src/chart-bar/chart-bar.scss +58 -0
  73. package/src/chart-bar/chart-bar.ts +306 -0
  74. package/src/chart-bar/chart-stacked-bar.ts +402 -0
  75. package/src/chart-bar/index.ts +2 -0
  76. package/src/index.ts +6 -0
  77. package/src/menu/menu-item/menu-item.ts +1 -1
  78. package/src/peacock-loader.ts +18 -0
  79. package/src/radio/index.ts +1 -0
  80. package/src/radio/radio.scss +181 -0
  81. package/src/radio/radio.ts +362 -0
  82. package/src/snackbar/demo/index.html +29 -0
  83. package/src/snackbar/index.ts +1 -0
  84. package/src/snackbar/snackbar.scss +73 -0
  85. package/src/snackbar/snackbar.ts +151 -0
  86. package/src/tabs/tab-group.ts +57 -28
  87. package/src/tabs/tab-panel.scss +3 -3
  88. package/src/tabs/tab-panel.ts +2 -0
  89. package/src/tabs/tab.scss +76 -2
  90. package/src/tabs/tab.ts +29 -7
  91. package/src/tabs/tabs.ts +15 -3
  92. package/dist/transform-DRuHEvar.js.map +0 -1
  93. package/dist/tree-view-CLolVlU0.js.map +0 -1
@@ -0,0 +1,402 @@
1
+ import { html, LitElement, PropertyValues } from 'lit';
2
+ import { property, query } from 'lit/decorators.js';
3
+ import { styleMap } from 'lit/directives/style-map.js';
4
+ import IndividualComponent from 'src/IndividualComponent.js';
5
+ import * as d3 from 'd3';
6
+ import styles from './chart-bar.scss';
7
+
8
+ export type ChartStackedSegment = {
9
+ name: string;
10
+ value: number;
11
+ label?: string;
12
+ color?: string;
13
+ };
14
+
15
+ export type ChartStackedBarItem = {
16
+ name: string;
17
+ label?: string;
18
+ segments: ChartStackedSegment[];
19
+ };
20
+
21
+ const chartColors: string[] = [];
22
+ ['purple', 'blue', 'red', 'green', 'yellow', 'orange'].forEach(colorName => {
23
+ chartColors.push(`var(--color-${colorName})`);
24
+ });
25
+
26
+ const DEFAULT_WIDTH = 520;
27
+ const DEFAULT_HEIGHT = 360;
28
+ const BAR_RADIUS = 8;
29
+ const DURATION = 450;
30
+
31
+ function debounce<T extends (...args: any[]) => void>(fn: T, wait: number): T {
32
+ let timer: ReturnType<typeof setTimeout>;
33
+ return ((...args: any[]) => {
34
+ clearTimeout(timer);
35
+ timer = setTimeout(() => fn(...args), wait);
36
+ }) as T;
37
+ }
38
+
39
+ /**
40
+ * @label Chart Stacked Bar
41
+ * @tag wc-chart-stacked-bar
42
+ * @rawTag chart-stacked-bar
43
+ * @summary A stacked bar chart that groups series by category using Material Design 3 tokens.
44
+ * @tags charts
45
+ *
46
+ * @example
47
+ * ```html
48
+ * <wc-chart-stacked-bar width="560" height="360"></wc-chart-stacked-bar>
49
+ * <script>
50
+ * document.querySelector('wc-chart-stacked-bar').data = [
51
+ * {
52
+ * name: 'q1',
53
+ * label: 'Q1',
54
+ * segments: [
55
+ * { name: 'mobile', label: 'Mobile', value: 40 },
56
+ * { name: 'web', label: 'Web', value: 25 },
57
+ * { name: 'store', label: 'Store', value: 15 },
58
+ * ],
59
+ * },
60
+ * {
61
+ * name: 'q2',
62
+ * label: 'Q2',
63
+ * segments: [
64
+ * { name: 'mobile', label: 'Mobile', value: 32 },
65
+ * { name: 'web', label: 'Web', value: 30 },
66
+ * { name: 'store', label: 'Store', value: 18 },
67
+ * ],
68
+ * },
69
+ * ];
70
+ * </script>
71
+ * ```
72
+ */
73
+ @IndividualComponent
74
+ export class ChartStackedBar extends LitElement {
75
+ static styles = [styles];
76
+
77
+ @query('svg')
78
+ private svgElement?: SVGElement;
79
+
80
+ /** Width of the chart in pixels. */
81
+ @property({ type: Number, reflect: true }) width: number = 0;
82
+
83
+ /** Height of the chart in pixels. */
84
+ @property({ type: Number, reflect: true }) height: number = DEFAULT_HEIGHT;
85
+
86
+ /** Margin around the chart drawing area. */
87
+ @property({ type: Number }) margin: number = 28;
88
+
89
+ /** Chart data array. Each item holds the stacked segments for a category. */
90
+ @property({ type: Array }) data: ChartStackedBarItem[] = [];
91
+
92
+ /** Whether to render total value labels above each stack. */
93
+ @property({ type: Boolean, attribute: 'show-values' }) showValues: boolean = true;
94
+
95
+ /** Whether to render the legend. */
96
+ @property({ type: Boolean, attribute: 'show-legend' }) showLegend: boolean = true;
97
+
98
+ private _initialized = false;
99
+
100
+ private _debouncedRenderChart = debounce(() => {
101
+ this._renderChart(true);
102
+ }, 200);
103
+
104
+ firstUpdated() {
105
+ this._renderChart(false);
106
+ }
107
+
108
+ updated(changedProperties: PropertyValues) {
109
+ if (!this._initialized) {
110
+ this._initialized = true;
111
+ return;
112
+ }
113
+ const watchedProps = [
114
+ 'width',
115
+ 'height',
116
+ 'margin',
117
+ 'data',
118
+ 'showValues',
119
+ 'showLegend',
120
+ ];
121
+ const hasChanged = watchedProps.some(prop => changedProperties.has(prop));
122
+ if (hasChanged) {
123
+ this._debouncedRenderChart();
124
+ }
125
+ }
126
+
127
+ private _getSegmentKeys() {
128
+ const keys = new Set<string>();
129
+ this.data?.forEach(item => {
130
+ item.segments?.forEach(segment => keys.add(segment.name));
131
+ });
132
+ return Array.from(keys);
133
+ }
134
+
135
+ private _getColorScale(keys: string[]) {
136
+ return d3
137
+ .scaleOrdinal<string, string>()
138
+ .domain(keys)
139
+ .range(chartColors);
140
+ }
141
+
142
+ private _getColorMap(
143
+ keys: string[],
144
+ scale: d3.ScaleOrdinal<string, string>,
145
+ ) {
146
+ const map = new Map<string, string>();
147
+ keys.forEach(key => {
148
+ const override = this.data
149
+ .map(item => item.segments.find(seg => seg.name === key)?.color)
150
+ .find(color => !!color);
151
+ map.set(key, override || scale(key));
152
+ });
153
+ return map;
154
+ }
155
+
156
+ private _getSegmentLabel(key: string) {
157
+ const segment = this.data
158
+ .map(item => item.segments.find(seg => seg.name === key))
159
+ .find(Boolean);
160
+ return segment?.label ?? key;
161
+ }
162
+
163
+ private _getTotals() {
164
+ return this.data.map(item =>
165
+ item.segments.reduce((sum, seg) => sum + seg.value, 0),
166
+ );
167
+ }
168
+
169
+ private _renderChart(animate: boolean) {
170
+ if (!this.svgElement) return;
171
+
172
+ const width = this.width > 0 ? this.width : DEFAULT_WIDTH;
173
+ const height = this.height > 0 ? this.height : DEFAULT_HEIGHT;
174
+ const margin = Math.max(this.margin, 16);
175
+ const data = this.data ?? [];
176
+
177
+ const svg = d3.select(this.svgElement);
178
+ svg.attr('width', width).attr('height', height);
179
+
180
+ const innerWidth = Math.max(width - margin * 2, 0);
181
+ const innerHeight = Math.max(height - margin * 2, 0);
182
+
183
+ const container = svg.select<SVGGElement>('.chart-container');
184
+ container.attr('transform', `translate(${margin},${margin})`);
185
+
186
+ if (!data.length || innerWidth === 0 || innerHeight === 0) {
187
+ container.select('.bars').selectAll('*').remove();
188
+ container.select('.x-axis').selectAll('*').remove();
189
+ container.select('.y-grid').selectAll('*').remove();
190
+ container.select('.value-labels').selectAll('*').remove();
191
+ return;
192
+ }
193
+
194
+ const keys = this._getSegmentKeys();
195
+ const colorScale = this._getColorScale(keys);
196
+ const colorMap = this._getColorMap(keys, colorScale);
197
+
198
+ const totals = this._getTotals();
199
+ const xScale = d3
200
+ .scaleBand<string>()
201
+ .domain(data.map(d => d.name))
202
+ .range([0, innerWidth])
203
+ .padding(0.3);
204
+ const maxValue = d3.max(totals) ?? 0;
205
+ const yScale = d3
206
+ .scaleLinear()
207
+ .domain([0, maxValue || 1])
208
+ .nice()
209
+ .range([innerHeight, 0]);
210
+
211
+ const stackedSeries = d3
212
+ .stack<ChartStackedBarItem, string>()
213
+ .keys(keys)
214
+ .value(
215
+ (d, key) => d.segments.find(segment => segment.name === key)?.value ?? 0,
216
+ )(data);
217
+
218
+ const yGrid = container.select<SVGGElement>('.y-grid');
219
+ yGrid
220
+ .call(
221
+ d3
222
+ .axisLeft(yScale)
223
+ .ticks(5)
224
+ .tickSize(-innerWidth)
225
+ .tickFormat(() => ''),
226
+ )
227
+ .selectAll('.tick text')
228
+ .remove();
229
+ yGrid.select('.domain').remove();
230
+ yGrid.selectAll('.tick line').attr('class', 'gridline');
231
+
232
+ const xAxis = container.select<SVGGElement>('.x-axis');
233
+ xAxis
234
+ .attr('transform', `translate(0,${innerHeight})`)
235
+ .call(
236
+ d3
237
+ .axisBottom(xScale)
238
+ .tickSizeOuter(0)
239
+ .tickFormat(name => {
240
+ const entry = data.find(d => d.name === name);
241
+ return entry?.label ?? name;
242
+ }),
243
+ );
244
+ xAxis.select('.domain').attr('stroke', 'var(--color-outline-variant)');
245
+ xAxis.selectAll('.tick line').remove();
246
+ xAxis
247
+ .selectAll('.tick text')
248
+ .attr('class', 'axis-label')
249
+ .attr('dy', '1.1em');
250
+
251
+ const barGroups = container
252
+ .select('.bars')
253
+ .selectAll<SVGGElement, d3.Series<ChartStackedBarItem, string>>(
254
+ '.bar-group',
255
+ )
256
+ .data(stackedSeries, series => series.key)
257
+ .join(
258
+ enter =>
259
+ enter
260
+ .append('g')
261
+ .attr('class', 'bar-group')
262
+ .style('fill', series => colorMap.get(series.key) ?? ''),
263
+ update => update,
264
+ exit => exit.remove(),
265
+ )
266
+ .style('fill', series => colorMap.get(series.key) ?? colorScale(series.key));
267
+
268
+ const segmentJoin = barGroups
269
+ .selectAll<SVGRectElement, d3.SeriesPoint<ChartStackedBarItem>>('rect')
270
+ .data(series => series, d => d.data.name)
271
+ .join(
272
+ enter =>
273
+ enter
274
+ .append('rect')
275
+ .attr('class', 'stacked-segment')
276
+ .attr('x', d => xScale(d.data.name) ?? 0)
277
+ .attr('width', xScale.bandwidth())
278
+ .attr('y', innerHeight)
279
+ .attr('height', 0)
280
+ .attr('rx', BAR_RADIUS)
281
+ .attr('ry', BAR_RADIUS),
282
+ update => update,
283
+ exit =>
284
+ exit
285
+ .transition()
286
+ .duration(DURATION)
287
+ .attr('y', innerHeight)
288
+ .attr('height', 0)
289
+ .remove(),
290
+ );
291
+
292
+ segmentJoin
293
+ .attr('x', d => xScale(d.data.name) ?? 0)
294
+ .attr('width', xScale.bandwidth())
295
+ .attr('rx', BAR_RADIUS)
296
+ .attr('ry', BAR_RADIUS);
297
+
298
+ if (animate) {
299
+ segmentJoin
300
+ .transition()
301
+ .duration(DURATION)
302
+ .attr('y', d => yScale(d[1]))
303
+ .attr('height', d => yScale(d[0]) - yScale(d[1]));
304
+ } else {
305
+ segmentJoin
306
+ .attr('y', d => yScale(d[1]))
307
+ .attr('height', d => yScale(d[0]) - yScale(d[1]));
308
+ }
309
+
310
+ const totalLabels = container
311
+ .select('.value-labels')
312
+ .selectAll<SVGTextElement, ChartStackedBarItem>('text')
313
+ .data(this.showValues ? data : [], d => d.name)
314
+ .join(
315
+ enter =>
316
+ enter
317
+ .append('text')
318
+ .attr('class', 'value-label')
319
+ .attr('text-anchor', 'middle')
320
+ .attr('x', d => (xScale(d.name) ?? 0) + xScale.bandwidth() / 2)
321
+ .attr('y', innerHeight - 6)
322
+ .text(d =>
323
+ d.segments
324
+ .reduce((sum, seg) => sum + seg.value, 0)
325
+ .toLocaleString(),
326
+ ),
327
+ update => update,
328
+ exit => exit.remove(),
329
+ );
330
+
331
+ const labelPosition = (item: ChartStackedBarItem) => {
332
+ const total = item.segments.reduce((sum, seg) => sum + seg.value, 0);
333
+ const offset = yScale(total) - 8;
334
+ return Math.min(offset, innerHeight - 8);
335
+ };
336
+
337
+ if (animate) {
338
+ totalLabels
339
+ .transition()
340
+ .duration(DURATION)
341
+ .attr('x', d => (xScale(d.name) ?? 0) + xScale.bandwidth() / 2)
342
+ .attr('y', d => labelPosition(d))
343
+ .text(d =>
344
+ d.segments
345
+ .reduce((sum, seg) => sum + seg.value, 0)
346
+ .toLocaleString(),
347
+ );
348
+ } else {
349
+ totalLabels
350
+ .attr('x', d => (xScale(d.name) ?? 0) + xScale.bandwidth() / 2)
351
+ .attr('y', d => labelPosition(d))
352
+ .text(d =>
353
+ d.segments
354
+ .reduce((sum, seg) => sum + seg.value, 0)
355
+ .toLocaleString(),
356
+ );
357
+ }
358
+ }
359
+
360
+ render() {
361
+ const keys = this._getSegmentKeys();
362
+ const colorScale = this._getColorScale(keys);
363
+ const colorMap = this._getColorMap(keys, colorScale);
364
+
365
+ const legendItems = keys.map(key => ({
366
+ name: this._getSegmentLabel(key),
367
+ color: colorMap.get(key) ?? colorScale(key),
368
+ }));
369
+
370
+ return html`
371
+ <div class="chart-frame">
372
+ <svg role="img" aria-label="Stacked bar chart">
373
+ <g class="chart-container">
374
+ <g class="y-grid"></g>
375
+ <g class="bars"></g>
376
+ <g class="x-axis"></g>
377
+ <g class="value-labels"></g>
378
+ </g>
379
+ </svg>
380
+ ${this.showLegend && legendItems.length
381
+ ? html`<div class="legend" role="list">
382
+ ${legendItems.map(
383
+ item => html`<span class="legend-item" role="listitem">
384
+ <span
385
+ class="swatch"
386
+ style=${styleMap({ background: item.color })}
387
+ ></span>
388
+ <span>${item.name}</span>
389
+ </span>`,
390
+ )}
391
+ </div>`
392
+ : null}
393
+ </div>
394
+ `;
395
+ }
396
+ }
397
+
398
+ declare global {
399
+ interface HTMLElementTagNameMap {
400
+ 'wc-chart-stacked-bar': ChartStackedBar;
401
+ }
402
+ }
@@ -0,0 +1,2 @@
1
+ export { ChartBar } from './chart-bar.js';
2
+ export { ChartStackedBar } from './chart-stacked-bar.js';
package/src/index.ts CHANGED
@@ -22,6 +22,7 @@ export { DatePicker } from './date-picker/index.js';
22
22
  export { TimePicker } from './time-picker/index.js';
23
23
  export { Textarea } from './textarea/index.js';
24
24
  export { Switch } from './switch/index.js';
25
+ export { Checkbox } from './checkbox/index.js';
25
26
  export { Spinner } from './spinner/index.js';
26
27
  export { Container } from './container/index.js';
27
28
 
@@ -36,8 +37,13 @@ export { CodeEditor } from './code-editor/index.js';
36
37
  export { Image } from './image/index.js';
37
38
  export { Tab, TabGroup, TabPanel, Tabs } from './tabs/index.js';
38
39
  export { Slider } from './slider/index.js';
40
+ export { ChartDonut } from './chart-donut/index.js';
39
41
  export { ChartDoughnut } from './chart-doughnut/index.js';
40
42
  export { ChartPie } from './chart-pie/index.js';
43
+ export { ChartBar, ChartStackedBar } from './chart-bar/index.js';
41
44
  export { Table } from './table/index.js';
42
45
  export { Pagination } from './pagination/index.js';
43
46
  export { TreeView, TreeNode } from './tree-view/index.js';
47
+ export { Card } from './card/index.js';
48
+ export { Snackbar } from './snackbar/index.js';
49
+ export { Radio } from './radio/index.js';
@@ -8,7 +8,7 @@ import colorStyles from './menu-item-colors.scss';
8
8
  * @label Menu Item
9
9
  * @tag wc-menu-item
10
10
  * @rawTag menu-item
11
- * @parentRawTag menu-list
11
+ * @parentRawTag menu
12
12
  * @summary An item in a menu list.
13
13
  * @tags navigation
14
14
  *
@@ -19,6 +19,7 @@ import { TimePicker } from './time-picker/time-picker.js';
19
19
  import { Textarea } from './textarea/textarea.js';
20
20
  import { Switch } from './switch/switch.js';
21
21
  import { Checkbox } from './checkbox/checkbox.js';
22
+ import { Radio } from './radio/radio.js';
22
23
 
23
24
  import { Menu } from './menu/menu/menu.js';
24
25
  import { MenuItem } from './menu/menu-item/menu-item.js';
@@ -51,6 +52,8 @@ import { Slider } from './slider/slider.js';
51
52
  import { Table } from './table/table.js';
52
53
  import { Pagination } from './pagination/pagination.js';
53
54
  import { TreeView } from './tree-view/tree-view.js';
55
+ import { Card } from './card/card.js';
56
+ import { Snackbar } from './snackbar/snackbar.js';
54
57
 
55
58
  const distDirectory = `${import.meta.url}/..`;
56
59
  await loadCSS(`${distDirectory}/assets/styles.css`);
@@ -135,6 +138,9 @@ const loaderConfig: LoaderConfig = {
135
138
  'wc-chip': {
136
139
  CustomElementClass: Chip,
137
140
  },
141
+ 'wc-card': {
142
+ CustomElementClass: Card,
143
+ },
138
144
  'wc-tag': {
139
145
  CustomElementClass: Tag,
140
146
  },
@@ -190,6 +196,9 @@ const loaderConfig: LoaderConfig = {
190
196
  'wc-checkbox': {
191
197
  CustomElementClass: Checkbox,
192
198
  },
199
+ 'wc-radio': {
200
+ CustomElementClass: Radio,
201
+ },
193
202
  'wc-spinner': {
194
203
  CustomElementClass: Spinner,
195
204
  },
@@ -226,12 +235,21 @@ const loaderConfig: LoaderConfig = {
226
235
  'wc-tree-node': {
227
236
  CustomElementClass: TreeView.Node,
228
237
  },
238
+ 'wc-snackbar': {
239
+ CustomElementClass: Snackbar,
240
+ },
229
241
  'wc-chart-doughnut': {
230
242
  importPath: `${distDirectory}/chart-doughnut.js`,
231
243
  },
232
244
  'wc-chart-pie': {
233
245
  importPath: `${distDirectory}/chart-pie.js`,
234
246
  },
247
+ 'wc-chart-bar': {
248
+ importPath: `${distDirectory}/chart-bar.js`,
249
+ },
250
+ 'wc-chart-stacked-bar': {
251
+ importPath: `${distDirectory}/chart-stacked-bar.js`,
252
+ },
235
253
  },
236
254
  };
237
255
 
@@ -0,0 +1 @@
1
+ export { Radio } from './radio.js';
@@ -0,0 +1,181 @@
1
+ @use '../../scss/mixin';
2
+
3
+ @include mixin.base-styles;
4
+
5
+ :host {
6
+ display: inline-block;
7
+ --radio-size: 20px;
8
+ --radio-dot-size: 12px;
9
+ --radio-selected-color: var(--color-primary);
10
+ --radio-unselected-color: var(--color-on-surface-variant);
11
+ --radio-state-layer-size: 40px;
12
+ --radio-disabled-opacity: 0.38;
13
+ }
14
+
15
+ .radio {
16
+ position: relative;
17
+ display: inline-flex;
18
+ align-items: center;
19
+ cursor: pointer;
20
+ user-select: none;
21
+ vertical-align: middle;
22
+ gap: 8px;
23
+
24
+ @include mixin.get-typography('body-medium');
25
+
26
+ .input-native {
27
+ position: absolute;
28
+ width: 1px;
29
+ height: 1px;
30
+ padding: 0;
31
+ margin: -1px;
32
+ overflow: hidden;
33
+ clip: rect(0, 0, 0, 0);
34
+ border: 0;
35
+ }
36
+
37
+ .container {
38
+ position: relative;
39
+ display: inline-flex;
40
+ align-items: center;
41
+ justify-content: center;
42
+ width: var(--radio-state-layer-size);
43
+ height: var(--radio-state-layer-size);
44
+ cursor: inherit;
45
+ outline: none;
46
+ flex-shrink: 0;
47
+ }
48
+
49
+ .state-layer {
50
+ position: absolute;
51
+ inset: 0;
52
+ border-radius: 50%;
53
+ opacity: 0;
54
+ transition: opacity var(--duration-short2) var(--easing-standard);
55
+ }
56
+
57
+ .outer-circle {
58
+ position: absolute;
59
+ width: var(--radio-size);
60
+ height: var(--radio-size);
61
+ border: 2px solid var(--radio-unselected-color);
62
+ border-radius: 50%;
63
+ box-sizing: border-box;
64
+ transition: border-color var(--duration-short2) var(--easing-standard);
65
+ }
66
+
67
+ .inner-circle {
68
+ position: absolute;
69
+ width: var(--radio-dot-size);
70
+ height: var(--radio-dot-size);
71
+ background: var(--radio-selected-color);
72
+ border-radius: 50%;
73
+ opacity: 0;
74
+ transform: scale(0.5);
75
+ transition:
76
+ transform var(--duration-short2) var(--easing-standard),
77
+ opacity var(--duration-short2) var(--easing-standard);
78
+ }
79
+
80
+ .label {
81
+ color: var(--color-on-surface);
82
+ cursor: inherit;
83
+ }
84
+
85
+ // Hover state
86
+ &:hover:not(.disabled):not(.readonly) {
87
+ .state-layer {
88
+ opacity: 0.08;
89
+ background: var(--color-on-surface);
90
+ }
91
+
92
+ &.state-checked .state-layer {
93
+ background: var(--radio-selected-color);
94
+ }
95
+ }
96
+
97
+ // Focus state
98
+ &.has-focus:not(.active):not(.disabled):not(.readonly) {
99
+ .state-layer {
100
+ opacity: 0.12;
101
+ background: var(--color-on-surface);
102
+ }
103
+
104
+ .container {
105
+ outline: 3px solid var(--color-primary);
106
+ outline-offset: 2px;
107
+ border-radius: 50%;
108
+ }
109
+
110
+ &.state-checked .state-layer {
111
+ background: var(--radio-selected-color);
112
+ }
113
+ }
114
+
115
+ // Active/pressed state
116
+ &.active:not(.disabled):not(.readonly) {
117
+ .state-layer {
118
+ opacity: 0.12;
119
+ background: var(--color-on-surface);
120
+ }
121
+
122
+ &.state-checked .state-layer {
123
+ background: var(--radio-selected-color);
124
+ }
125
+ }
126
+ }
127
+
128
+ // Checked state
129
+ .radio.state-checked {
130
+ .outer-circle {
131
+ border-color: var(--radio-selected-color);
132
+ }
133
+
134
+ .inner-circle {
135
+ opacity: 1;
136
+ transform: scale(1);
137
+ }
138
+ }
139
+
140
+ // Readonly state
141
+ .radio.readonly {
142
+ cursor: default;
143
+
144
+ .state-layer {
145
+ display: none;
146
+ }
147
+
148
+ .outer-circle {
149
+ border-color: var(--color-on-surface-variant);
150
+ }
151
+
152
+ &.state-checked {
153
+ .inner-circle {
154
+ background: var(--color-on-surface-variant);
155
+ }
156
+ }
157
+ }
158
+
159
+ // Disabled state
160
+ .radio.disabled {
161
+ cursor: not-allowed;
162
+ opacity: var(--radio-disabled-opacity);
163
+
164
+ .state-layer {
165
+ display: none;
166
+ }
167
+
168
+ .label {
169
+ color: var(--color-on-surface);
170
+ }
171
+
172
+ .outer-circle {
173
+ border-color: var(--color-on-surface);
174
+ }
175
+
176
+ &.state-checked {
177
+ .inner-circle {
178
+ background: var(--color-on-surface);
179
+ }
180
+ }
181
+ }