@redvars/peacock 3.5.1 → 3.6.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.
- package/dist/{BaseButton-DuASuVth.js → BaseButton-BNFAYn-S.js} +2 -2
- package/dist/{BaseButton-DuASuVth.js.map → BaseButton-BNFAYn-S.js.map} +1 -1
- package/dist/BaseInput-14YmcfK7.js +27 -0
- package/dist/BaseInput-14YmcfK7.js.map +1 -0
- package/dist/banner.js +2 -3
- package/dist/banner.js.map +1 -1
- package/dist/{button-DouvOfEU.js → button-colors-Ccys3hvS.js} +5 -294
- package/dist/button-colors-Ccys3hvS.js.map +1 -0
- package/dist/button-group.js +226 -6
- package/dist/button-group.js.map +1 -1
- package/dist/button.js +294 -8
- package/dist/button.js.map +1 -1
- package/dist/calendar-column-view.js +634 -0
- package/dist/calendar-column-view.js.map +1 -0
- package/dist/calendar-event-BrQ_SEKD.js +199 -0
- package/dist/calendar-event-BrQ_SEKD.js.map +1 -0
- package/dist/calendar-month-view.js +376 -0
- package/dist/calendar-month-view.js.map +1 -0
- package/dist/calendar.js +339 -0
- package/dist/calendar.js.map +1 -0
- package/dist/canvas.js +361 -0
- package/dist/canvas.js.map +1 -0
- package/dist/cb-compound-expression.js +125 -0
- package/dist/cb-compound-expression.js.map +1 -0
- package/dist/cb-divider.js +150 -0
- package/dist/cb-divider.js.map +1 -0
- package/dist/cb-expression.js +75 -0
- package/dist/cb-expression.js.map +1 -0
- package/dist/cb-predicate.js +137 -0
- package/dist/cb-predicate.js.map +1 -0
- package/dist/code-editor.js +2 -1
- package/dist/code-editor.js.map +1 -1
- package/dist/code-highlighter.js +1 -1
- package/dist/code-highlighter.js.map +1 -1
- package/dist/condition-builder.js +58 -0
- package/dist/condition-builder.js.map +1 -0
- package/dist/custom-elements-jsdocs.json +8479 -3965
- package/dist/custom-elements.json +15228 -7544
- package/dist/dropdown-button.js +216 -0
- package/dist/dropdown-button.js.map +1 -0
- package/dist/event-manager-D-QCmUgR.js +113 -0
- package/dist/event-manager-D-QCmUgR.js.map +1 -0
- package/dist/fab.js +1 -1
- package/dist/flow-designer-DvTUrDp5.js +1656 -0
- package/dist/flow-designer-DvTUrDp5.js.map +1 -0
- package/dist/flow-designer-node-BWrPuxAR.js +548 -0
- package/dist/flow-designer-node-BWrPuxAR.js.map +1 -0
- package/dist/flow-designer-node.js +4 -0
- package/dist/flow-designer-node.js.map +1 -0
- package/dist/flow-designer.js +16 -0
- package/dist/flow-designer.js.map +1 -0
- package/dist/html-editor.js +27516 -0
- package/dist/html-editor.js.map +1 -0
- package/dist/icon-button-CK1ZuE-2.js +247 -0
- package/dist/icon-button-CK1ZuE-2.js.map +1 -0
- package/dist/index.js +29 -6
- package/dist/index.js.map +1 -1
- package/dist/{is-dark-mode-DicqGkCJ.js → is-dark-mode-DOcaw4Yq.js} +2 -27
- package/dist/is-dark-mode-DOcaw4Yq.js.map +1 -0
- package/dist/modal.js +412 -0
- package/dist/modal.js.map +1 -0
- package/dist/{navigation-rail-Lxetd5-Z.js → navigation-rail-DTTkqohi.js} +1049 -2391
- package/dist/navigation-rail-DTTkqohi.js.map +1 -0
- package/dist/notification-manager.js +268 -0
- package/dist/notification-manager.js.map +1 -0
- package/dist/peacock-loader.js +93 -8
- package/dist/peacock-loader.js.map +1 -1
- package/dist/popover-NC7b1lTq.js +1971 -0
- package/dist/popover-NC7b1lTq.js.map +1 -0
- package/dist/popover-content.js +125 -0
- package/dist/popover-content.js.map +1 -0
- package/dist/popover.js +4 -0
- package/dist/popover.js.map +1 -0
- package/dist/split-button.js +388 -0
- package/dist/split-button.js.map +1 -0
- package/dist/src/__controllers/floating-controller.d.ts +35 -0
- package/dist/src/calendar/base-event.d.ts +10 -0
- package/dist/src/calendar/calendar-column-view.d.ts +41 -0
- package/dist/src/calendar/calendar-event.d.ts +7 -0
- package/dist/src/calendar/calendar-month-view.d.ts +31 -0
- package/dist/src/calendar/calendar.d.ts +65 -0
- package/dist/src/calendar/event-manager.d.ts +17 -0
- package/dist/src/calendar/index.d.ts +4 -0
- package/dist/src/calendar/types.d.ts +13 -0
- package/dist/src/calendar/utils.d.ts +31 -0
- package/dist/src/canvas/canvas.d.ts +92 -0
- package/dist/src/canvas/index.d.ts +2 -0
- package/dist/src/condition-builder/cb-compound-expression.d.ts +31 -0
- package/dist/src/condition-builder/cb-divider.d.ts +26 -0
- package/dist/src/condition-builder/cb-expression.d.ts +31 -0
- package/dist/src/condition-builder/cb-predicate.d.ts +30 -0
- package/dist/src/condition-builder/condition-builder.d.ts +27 -0
- package/dist/src/condition-builder/index.d.ts +5 -0
- package/dist/src/dropdown-button/dropdown-button.d.ts +68 -0
- package/dist/src/dropdown-button/index.d.ts +1 -0
- package/dist/src/flow-designer/commands.d.ts +66 -0
- package/dist/src/flow-designer/flow-designer-node.d.ts +46 -0
- package/dist/src/flow-designer/flow-designer.d.ts +133 -0
- package/dist/src/flow-designer/index.d.ts +7 -0
- package/dist/src/flow-designer/layout.d.ts +30 -0
- package/dist/src/flow-designer/types.d.ts +142 -0
- package/dist/src/flow-designer/validation.d.ts +43 -0
- package/dist/src/flow-designer/workflow-utils.d.ts +40 -0
- package/dist/src/html-editor/html-editor.d.ts +89 -0
- package/dist/src/html-editor/index.d.ts +2 -0
- package/dist/src/index.d.ts +15 -0
- package/dist/src/list/index.d.ts +2 -0
- package/dist/src/list/list-item.d.ts +35 -0
- package/dist/src/list/list.d.ts +28 -0
- package/dist/src/menu/menu/menu.d.ts +5 -7
- package/dist/src/menu/menu-item/menu-item.d.ts +14 -13
- package/dist/src/modal/index.d.ts +1 -0
- package/dist/src/modal/modal.d.ts +57 -0
- package/dist/src/navigation-rail/navigation-rail.d.ts +3 -7
- package/dist/src/notification-manager/index.d.ts +1 -0
- package/dist/src/notification-manager/notification-manager.d.ts +44 -0
- package/dist/src/number-field/number-field.d.ts +2 -2
- package/dist/src/popover/index.d.ts +2 -0
- package/dist/src/popover/popover-content.d.ts +29 -0
- package/dist/src/popover/popover.d.ts +62 -0
- package/dist/src/split-button/index.d.ts +1 -0
- package/dist/src/split-button/split-button.d.ts +72 -0
- package/dist/src/svg/index.d.ts +1 -0
- package/dist/src/svg/svg.d.ts +38 -0
- package/dist/src/toolbar/toolbar.d.ts +3 -3
- package/dist/src/tooltip/tooltip.d.ts +2 -15
- package/dist/test/flow-designer.test.d.ts +1 -0
- package/dist/toolbar.js +3 -3
- package/dist/toolbar.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +10 -2
- package/readme.md +3 -3
- package/src/__controllers/floating-controller.ts +237 -0
- package/src/banner/banner.scss +2 -3
- package/src/button/button/button.ts +1 -0
- package/src/calendar/base-event.ts +49 -0
- package/src/calendar/calendar-column-view.scss +326 -0
- package/src/calendar/calendar-column-view.ts +392 -0
- package/src/calendar/calendar-event.ts +20 -0
- package/src/calendar/calendar-month-view.scss +192 -0
- package/src/calendar/calendar-month-view.ts +244 -0
- package/src/calendar/calendar.scss +71 -0
- package/src/calendar/calendar.ts +298 -0
- package/src/calendar/event-manager.ts +117 -0
- package/src/calendar/index.ts +4 -0
- package/src/calendar/types.ts +14 -0
- package/src/calendar/utils.ts +180 -0
- package/src/canvas/canvas.scss +60 -0
- package/src/canvas/canvas.ts +391 -0
- package/src/canvas/index.ts +2 -0
- package/src/code-highlighter/code-highlighter.ts +1 -1
- package/src/condition-builder/cb-compound-expression.scss +37 -0
- package/src/condition-builder/cb-compound-expression.ts +80 -0
- package/src/condition-builder/cb-divider.scss +93 -0
- package/src/condition-builder/cb-divider.ts +56 -0
- package/src/condition-builder/cb-expression.scss +14 -0
- package/src/condition-builder/cb-expression.ts +49 -0
- package/src/condition-builder/cb-predicate.scss +35 -0
- package/src/condition-builder/cb-predicate.ts +102 -0
- package/src/condition-builder/condition-builder.scss +13 -0
- package/src/condition-builder/condition-builder.ts +38 -0
- package/src/condition-builder/index.ts +5 -0
- package/src/dropdown-button/demo/index.html +110 -0
- package/src/dropdown-button/dropdown-button.scss +22 -0
- package/src/dropdown-button/dropdown-button.ts +206 -0
- package/src/dropdown-button/index.ts +1 -0
- package/src/flow-designer/DEMO.md +239 -0
- package/src/flow-designer/commands.ts +278 -0
- package/src/flow-designer/flow-designer-node.ts +172 -0
- package/src/flow-designer/flow-designer.scss +457 -0
- package/src/flow-designer/flow-designer.ts +611 -0
- package/src/flow-designer/index.ts +41 -0
- package/src/flow-designer/layout.ts +357 -0
- package/src/flow-designer/types.ts +166 -0
- package/src/flow-designer/validation.ts +284 -0
- package/src/flow-designer/workflow-utils.ts +282 -0
- package/src/html-editor/html-editor.scss +188 -0
- package/src/html-editor/html-editor.ts +491 -0
- package/src/html-editor/index.ts +3 -0
- package/src/index.ts +27 -1
- package/src/list/index.ts +2 -0
- package/src/list/list-item.scss +111 -0
- package/src/list/list-item.ts +175 -0
- package/src/list/list.scss +24 -0
- package/src/list/list.ts +51 -0
- package/src/menu/menu/menu.scss +2 -2
- package/src/menu/menu/menu.ts +91 -101
- package/src/menu/menu-item/menu-item.scss +4 -0
- package/src/menu/menu-item/menu-item.ts +82 -78
- package/src/modal/index.ts +1 -0
- package/src/modal/modal.scss +206 -0
- package/src/modal/modal.ts +195 -0
- package/src/navigation-rail/navigation-rail-item.scss +7 -38
- package/src/navigation-rail/navigation-rail-item.ts +1 -2
- package/src/navigation-rail/navigation-rail.scss +17 -21
- package/src/navigation-rail/navigation-rail.ts +6 -9
- package/src/notification-manager/index.ts +1 -0
- package/src/notification-manager/notification-manager.scss +113 -0
- package/src/notification-manager/notification-manager.ts +199 -0
- package/src/number-field/number-field.ts +2 -2
- package/src/peacock-loader.ts +83 -0
- package/src/popover/index.ts +2 -0
- package/src/popover/popover-content.scss +69 -0
- package/src/popover/popover-content.ts +51 -0
- package/src/popover/popover.scss +7 -0
- package/src/popover/popover.ts +170 -0
- package/src/split-button/index.ts +1 -0
- package/src/split-button/split-button-colors.scss +56 -0
- package/src/split-button/split-button-sizes.scss +28 -0
- package/src/split-button/split-button.scss +79 -0
- package/src/split-button/split-button.ts +236 -0
- package/src/svg/index.ts +1 -0
- package/src/svg/svg.scss +91 -0
- package/src/svg/svg.ts +160 -0
- package/src/table/table.ts +2 -2
- package/src/toolbar/toolbar.ts +3 -3
- package/src/tooltip/tooltip.scss +4 -3
- package/src/tooltip/tooltip.ts +46 -104
- package/dist/button-DouvOfEU.js.map +0 -1
- package/dist/button-group-CEdMwvJJ.js +0 -464
- package/dist/button-group-CEdMwvJJ.js.map +0 -1
- package/dist/is-dark-mode-DicqGkCJ.js.map +0 -1
- package/dist/navigation-rail-Lxetd5-Z.js.map +0 -1
- package/dist/src/menu/menu/MenuSurfaceController.d.ts +0 -18
- package/src/menu/menu/MenuSurfaceController.ts +0 -61
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
@mixin _split-button-color($color) {
|
|
2
|
+
--filled-split-button-container-color: var(--color-#{$color});
|
|
3
|
+
--filled-split-button-label-text-color: var(--color-on-#{$color});
|
|
4
|
+
|
|
5
|
+
--tonal-split-button-container-color: var(--color-#{$color}-container);
|
|
6
|
+
--tonal-split-button-label-text-color: var(--color-on-#{$color}-container);
|
|
7
|
+
|
|
8
|
+
--outlined-split-button-outline-color: var(--color-#{$color});
|
|
9
|
+
--outlined-split-button-label-text-color: var(--color-#{$color});
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
:host([color=primary]) {
|
|
13
|
+
@include _split-button-color(primary);
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
:host([color=secondary]) {
|
|
17
|
+
@include _split-button-color(secondary);
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
:host([color=tertiary]) {
|
|
21
|
+
@include _split-button-color(tertiary);
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
:host([color=success]) {
|
|
25
|
+
@include _split-button-color(success);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
:host([color=danger]) {
|
|
29
|
+
@include _split-button-color(error);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
:host([color=warning]) {
|
|
33
|
+
@include _split-button-color(warning);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
:host([color=on-surface]) {
|
|
37
|
+
--filled-split-button-container-color: var(--color-on-surface);
|
|
38
|
+
--filled-split-button-label-text-color: var(--color-surface);
|
|
39
|
+
|
|
40
|
+
--tonal-split-button-container-color: var(--color-on-surface-container);
|
|
41
|
+
--tonal-split-button-label-text-color: var(--color-surface-container-high);
|
|
42
|
+
|
|
43
|
+
--outlined-split-button-outline-color: var(--color-on-surface);
|
|
44
|
+
--outlined-split-button-label-text-color: var(--color-on-surface);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
:host([color=surface]) {
|
|
48
|
+
--filled-split-button-container-color: var(--color-surface-container-high);
|
|
49
|
+
--filled-split-button-label-text-color: var(--color-on-surface);
|
|
50
|
+
|
|
51
|
+
--tonal-split-button-container-color: var(--color-surface-container-high);
|
|
52
|
+
--tonal-split-button-label-text-color: var(--color-on-surface-container);
|
|
53
|
+
|
|
54
|
+
--outlined-split-button-outline-color: var(--color-on-surface);
|
|
55
|
+
--outlined-split-button-label-text-color: var(--color-on-surface);
|
|
56
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
:host([size='xs']),
|
|
2
|
+
:host([size='extra-small']) {
|
|
3
|
+
--split-button-icon-size: 1rem;
|
|
4
|
+
}
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
:host([size='sm']),
|
|
8
|
+
:host([size='small']) {
|
|
9
|
+
--split-button-icon-size: 1.125rem;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
:host([size='md']),
|
|
14
|
+
:host([size='medium']) {
|
|
15
|
+
--split-button-icon-size: 1.25rem;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
:host([size='lg']),
|
|
20
|
+
:host([size='large']) {
|
|
21
|
+
--split-button-icon-size: 1.5rem;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
:host([size='xl']),
|
|
26
|
+
:host([size='extra-large']) {
|
|
27
|
+
--split-button-icon-size: 2rem;
|
|
28
|
+
}
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
@use '../../scss/mixin';
|
|
2
|
+
|
|
3
|
+
@include mixin.base-styles;
|
|
4
|
+
|
|
5
|
+
:host {
|
|
6
|
+
display: inline-flex;
|
|
7
|
+
position: relative;
|
|
8
|
+
|
|
9
|
+
--split-button-container-shape: var(--shape-corner-medium);
|
|
10
|
+
--split-button-gap: 0.125rem;
|
|
11
|
+
--split-button-icon-size: 1.125rem;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
.split-button {
|
|
15
|
+
display: inline-flex;
|
|
16
|
+
align-items: center;
|
|
17
|
+
gap: var(--split-button-gap);
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
.action-button {
|
|
21
|
+
--button-container-shape: var(--split-button-container-shape);
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
.dropdown-trigger {
|
|
25
|
+
--button-container-shape: var(--split-button-container-shape);
|
|
26
|
+
--button-icon-size: var(--split-button-icon-size);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
.dropdown-icon {
|
|
30
|
+
transition: transform 200ms ease;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
.dropdown-trigger.active .dropdown-icon {
|
|
34
|
+
transform: rotate(180deg);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/* ── Variant: Filled ────────────────────────────────────── */
|
|
38
|
+
|
|
39
|
+
.split-button.variant-filled {
|
|
40
|
+
.action-button,
|
|
41
|
+
.dropdown-trigger {
|
|
42
|
+
--filled-button-container-color: var(--filled-split-button-container-color);
|
|
43
|
+
--filled-button-label-text-color: var(--filled-split-button-label-text-color);
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
/* ── Variant: Tonal ─────────────────────────────────────── */
|
|
49
|
+
|
|
50
|
+
.split-button.variant-tonal {
|
|
51
|
+
.action-button,
|
|
52
|
+
.dropdown-trigger {
|
|
53
|
+
--tonal-button-container-color: var(--tonal-split-button-container-color);
|
|
54
|
+
--tonal-button-label-text-color: var(--tonal-split-button-label-text-color);
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
/* ── Variant: Outlined ──────────────────────────────────── */
|
|
60
|
+
|
|
61
|
+
.split-button.variant-outlined {
|
|
62
|
+
.action-button,
|
|
63
|
+
.dropdown-trigger {
|
|
64
|
+
--outlined-button-outline-color: var(--outlined-split-button-outline-color, var(--color-outline));
|
|
65
|
+
--outlined-button-label-text-color: var(--outlined-split-button-label-text-color);
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
:host([block]) {
|
|
70
|
+
width: 100%;
|
|
71
|
+
|
|
72
|
+
.split-button {
|
|
73
|
+
width: 100%;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
.action-button {
|
|
77
|
+
flex: 1;
|
|
78
|
+
}
|
|
79
|
+
}
|
|
@@ -0,0 +1,236 @@
|
|
|
1
|
+
import { html, LitElement } from 'lit';
|
|
2
|
+
import { property, query, state } from 'lit/decorators.js';
|
|
3
|
+
import { classMap } from 'lit/directives/class-map.js';
|
|
4
|
+
import IndividualComponent from '@/IndividualComponent.js';
|
|
5
|
+
import styles from './split-button.scss';
|
|
6
|
+
import colorStyles from './split-button-colors.scss';
|
|
7
|
+
import sizeStyles from './split-button-sizes.scss';
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* @label Split Button
|
|
11
|
+
* @tag wc-split-button
|
|
12
|
+
* @rawTag split-button
|
|
13
|
+
*
|
|
14
|
+
* @summary A split button lets users perform a default action or choose from a set of related actions via a dropdown menu.
|
|
15
|
+
* @overview
|
|
16
|
+
* <p>A split button combines a primary action button with a dropdown arrow that opens a menu. Following M3 Material Design, the split button provides a default action alongside a set of secondary options, reducing clutter while keeping alternative actions accessible.</p>
|
|
17
|
+
*
|
|
18
|
+
* @cssprop --split-button-container-shape: Defines the border radius of the split button container shape.
|
|
19
|
+
*
|
|
20
|
+
* @cssprop --filled-split-button-container-color: Color of the filled split button container.
|
|
21
|
+
* @cssprop --filled-split-button-label-text-color: Text color of the filled split button label.
|
|
22
|
+
*
|
|
23
|
+
* @cssprop --outlined-split-button-container-color: Color of the outlined split button container.
|
|
24
|
+
* @cssprop --outlined-split-button-label-text-color: Text color of the outlined split button label.
|
|
25
|
+
*
|
|
26
|
+
* @cssprop --tonal-split-button-container-color: Color of the tonal split button container.
|
|
27
|
+
* @cssprop --tonal-split-button-label-text-color: Text color of the tonal split button label.
|
|
28
|
+
*
|
|
29
|
+
* @fires {MouseEvent} click - Dispatched when the primary action button is clicked.
|
|
30
|
+
* @fires {CustomEvent} toggle-menu - Dispatched when the dropdown menu is opened or closed.
|
|
31
|
+
*
|
|
32
|
+
* @example
|
|
33
|
+
* ```html
|
|
34
|
+
* <wc-split-button>
|
|
35
|
+
* Save
|
|
36
|
+
* <wc-menu-item slot="menu">Save as draft</wc-menu-item>
|
|
37
|
+
* <wc-menu-item slot="menu">Save and publish</wc-menu-item>
|
|
38
|
+
* </wc-split-button>
|
|
39
|
+
* ```
|
|
40
|
+
* @tags controls
|
|
41
|
+
*/
|
|
42
|
+
@IndividualComponent
|
|
43
|
+
export class SplitButton extends LitElement {
|
|
44
|
+
static override styles = [styles, colorStyles, sizeStyles];
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* Button size.
|
|
48
|
+
* Possible values are `"xs"`, `"sm"`, `"md"`, `"lg"`, `"xl"`. Defaults to `"sm"`.
|
|
49
|
+
*/
|
|
50
|
+
@property({ reflect: true }) size: 'xs' | 'sm' | 'md' | 'lg' | 'xl' = 'sm';
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* The visual style of the split button.
|
|
54
|
+
*
|
|
55
|
+
* Possible variant values:
|
|
56
|
+
* `"filled"` is a filled button.
|
|
57
|
+
* `"outlined"` is an outlined button.
|
|
58
|
+
* `"tonal"` is a light color button.
|
|
59
|
+
*/
|
|
60
|
+
@property({ reflect: true }) variant: 'filled' | 'tonal' | 'outlined' =
|
|
61
|
+
'filled';
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* Defines the primary color of the split button.
|
|
65
|
+
*/
|
|
66
|
+
@property({ reflect: true }) color:
|
|
67
|
+
| 'primary'
|
|
68
|
+
| 'secondary'
|
|
69
|
+
| 'tertiary'
|
|
70
|
+
| 'success'
|
|
71
|
+
| 'danger'
|
|
72
|
+
| 'warning'
|
|
73
|
+
| 'surface'
|
|
74
|
+
| 'on-surface' = 'primary';
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* Whether the split button is disabled.
|
|
78
|
+
*/
|
|
79
|
+
@property({ type: Boolean, reflect: true }) disabled = false;
|
|
80
|
+
|
|
81
|
+
@state() private _menuOpen = false;
|
|
82
|
+
|
|
83
|
+
@query('.dropdown-trigger') private readonly _dropdownButton!: HTMLElement;
|
|
84
|
+
|
|
85
|
+
@query('wc-menu') private readonly _menu!: HTMLElement & {
|
|
86
|
+
open: boolean;
|
|
87
|
+
anchorElement: HTMLElement | null;
|
|
88
|
+
show: () => void;
|
|
89
|
+
close: () => void;
|
|
90
|
+
};
|
|
91
|
+
|
|
92
|
+
private _menuId = `split-menu-${Math.random().toString(36).slice(2, 9)}`;
|
|
93
|
+
|
|
94
|
+
override focus() {
|
|
95
|
+
const btn =
|
|
96
|
+
this.shadowRoot?.querySelector<HTMLElement>('.action-button');
|
|
97
|
+
btn?.focus();
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
private _onActionClick(event: MouseEvent) {
|
|
101
|
+
if (this.disabled) {
|
|
102
|
+
event.stopImmediatePropagation();
|
|
103
|
+
event.preventDefault();
|
|
104
|
+
return;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
// Close menu if open
|
|
108
|
+
if (this._menuOpen) {
|
|
109
|
+
this._menu?.close();
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
private _onDropdownClick(event: MouseEvent) {
|
|
114
|
+
event.stopPropagation();
|
|
115
|
+
if (this.disabled) return;
|
|
116
|
+
|
|
117
|
+
if (this._menuOpen) {
|
|
118
|
+
this._menu?.close();
|
|
119
|
+
} else {
|
|
120
|
+
this._menu.anchorElement = this;
|
|
121
|
+
this._menu?.show();
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
private _onMenuOpened = () => {
|
|
126
|
+
this._menuOpen = true;
|
|
127
|
+
this.dispatchEvent(
|
|
128
|
+
new CustomEvent('toggle-menu', {
|
|
129
|
+
detail: { open: true },
|
|
130
|
+
bubbles: true,
|
|
131
|
+
composed: true,
|
|
132
|
+
}),
|
|
133
|
+
);
|
|
134
|
+
};
|
|
135
|
+
|
|
136
|
+
private _onMenuClosed = () => {
|
|
137
|
+
this._menuOpen = false;
|
|
138
|
+
this.dispatchEvent(
|
|
139
|
+
new CustomEvent('toggle-menu', {
|
|
140
|
+
detail: { open: false },
|
|
141
|
+
bubbles: true,
|
|
142
|
+
composed: true,
|
|
143
|
+
}),
|
|
144
|
+
);
|
|
145
|
+
};
|
|
146
|
+
|
|
147
|
+
private _onKeyDown = (event: KeyboardEvent) => {
|
|
148
|
+
if (this.disabled) return;
|
|
149
|
+
|
|
150
|
+
if (
|
|
151
|
+
event.key === 'ArrowDown' &&
|
|
152
|
+
event.target === this._dropdownButton
|
|
153
|
+
) {
|
|
154
|
+
event.preventDefault();
|
|
155
|
+
if (!this._menuOpen) {
|
|
156
|
+
this._menu.anchorElement = this;
|
|
157
|
+
this._menu?.show();
|
|
158
|
+
}
|
|
159
|
+
// Focus the menu so keyboard nav works
|
|
160
|
+
requestAnimationFrame(() => this._menu?.focus());
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
if (event.key === 'Escape' && this._menuOpen) {
|
|
164
|
+
this._menu?.close();
|
|
165
|
+
this._dropdownButton?.focus();
|
|
166
|
+
}
|
|
167
|
+
};
|
|
168
|
+
|
|
169
|
+
override connectedCallback() {
|
|
170
|
+
super.connectedCallback();
|
|
171
|
+
this.addEventListener('keydown', this._onKeyDown);
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
override disconnectedCallback() {
|
|
175
|
+
this.removeEventListener('keydown', this._onKeyDown);
|
|
176
|
+
super.disconnectedCallback();
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
override render() {
|
|
180
|
+
const actionClasses = {
|
|
181
|
+
'action-button': true,
|
|
182
|
+
disabled: this.disabled,
|
|
183
|
+
};
|
|
184
|
+
|
|
185
|
+
const dropdownClasses = {
|
|
186
|
+
'dropdown-trigger': true,
|
|
187
|
+
active: this._menuOpen,
|
|
188
|
+
disabled: this.disabled,
|
|
189
|
+
};
|
|
190
|
+
|
|
191
|
+
const containerClasses = {
|
|
192
|
+
'split-button': true,
|
|
193
|
+
[`variant-${this.variant}`]: true,
|
|
194
|
+
disabled: this.disabled,
|
|
195
|
+
};
|
|
196
|
+
|
|
197
|
+
return html`
|
|
198
|
+
<div class=${classMap(containerClasses)}>
|
|
199
|
+
<wc-button
|
|
200
|
+
class=${classMap(actionClasses)}
|
|
201
|
+
size=${this.size}
|
|
202
|
+
variant=${this.variant}
|
|
203
|
+
?disabled=${this.disabled}
|
|
204
|
+
@click=${this._onActionClick}
|
|
205
|
+
>
|
|
206
|
+
<slot></slot>
|
|
207
|
+
</wc-button>
|
|
208
|
+
|
|
209
|
+
<wc-icon-button
|
|
210
|
+
class=${classMap(dropdownClasses)}
|
|
211
|
+
size=${this.size}
|
|
212
|
+
variant=${this.variant}
|
|
213
|
+
?disabled=${this.disabled}
|
|
214
|
+
.configAria=${{
|
|
215
|
+
'aria-haspopup': 'menu',
|
|
216
|
+
'aria-expanded': String(this._menuOpen),
|
|
217
|
+
'aria-controls': this._menuId,
|
|
218
|
+
'aria-label': 'Open split button menu',
|
|
219
|
+
}}
|
|
220
|
+
@click=${this._onDropdownClick}
|
|
221
|
+
>
|
|
222
|
+
<wc-icon class="dropdown-icon" name="arrow_drop_down" aria-hidden="true"></wc-icon>
|
|
223
|
+
</wc-icon-button>
|
|
224
|
+
</div>
|
|
225
|
+
|
|
226
|
+
<wc-menu
|
|
227
|
+
id=${this._menuId}
|
|
228
|
+
placement="bottom-end"
|
|
229
|
+
@opened=${this._onMenuOpened}
|
|
230
|
+
@closed=${this._onMenuClosed}
|
|
231
|
+
>
|
|
232
|
+
<slot name="menu"></slot>
|
|
233
|
+
</wc-menu>
|
|
234
|
+
`;
|
|
235
|
+
}
|
|
236
|
+
}
|
package/src/svg/index.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { Svg } from './svg.js';
|
package/src/svg/svg.scss
ADDED
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
@use '../../scss/mixin';
|
|
2
|
+
|
|
3
|
+
@include mixin.base-styles;
|
|
4
|
+
|
|
5
|
+
:host {
|
|
6
|
+
display: inline-flex;
|
|
7
|
+
vertical-align: middle;
|
|
8
|
+
--svg-size: inherit;
|
|
9
|
+
--svg-color: inherit;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
.svg-wrapper {
|
|
13
|
+
height: var(--svg-size, 1rem);
|
|
14
|
+
width: var(--svg-size, 1rem);
|
|
15
|
+
display: inline-flex;
|
|
16
|
+
align-items: center;
|
|
17
|
+
justify-content: center;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
.svg-content {
|
|
21
|
+
height: 100%;
|
|
22
|
+
width: 100%;
|
|
23
|
+
display: inline-flex;
|
|
24
|
+
align-items: center;
|
|
25
|
+
justify-content: center;
|
|
26
|
+
|
|
27
|
+
svg {
|
|
28
|
+
fill: var(--svg-color);
|
|
29
|
+
height: 100%;
|
|
30
|
+
width: 100%;
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
.svg-content.clickable {
|
|
35
|
+
cursor: zoom-in;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
.placeholder {
|
|
39
|
+
display: block;
|
|
40
|
+
height: 100%;
|
|
41
|
+
width: 100%;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
.preview-overlay {
|
|
45
|
+
display: none;
|
|
46
|
+
position: fixed;
|
|
47
|
+
inset: 0;
|
|
48
|
+
z-index: 9999;
|
|
49
|
+
background: rgba(0, 0, 0, 0.85);
|
|
50
|
+
align-items: center;
|
|
51
|
+
justify-content: center;
|
|
52
|
+
cursor: zoom-out;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
.preview-overlay.open {
|
|
56
|
+
display: flex;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
.preview-close {
|
|
60
|
+
position: absolute;
|
|
61
|
+
top: 1rem;
|
|
62
|
+
right: 1rem;
|
|
63
|
+
background: transparent;
|
|
64
|
+
border: none;
|
|
65
|
+
color: #fff;
|
|
66
|
+
font-size: 1.5rem;
|
|
67
|
+
cursor: pointer;
|
|
68
|
+
line-height: 1;
|
|
69
|
+
padding: 0.25rem 0.5rem;
|
|
70
|
+
|
|
71
|
+
&:focus-visible {
|
|
72
|
+
outline: 2px solid #fff;
|
|
73
|
+
outline-offset: 2px;
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
.preview-content {
|
|
78
|
+
max-width: 90vw;
|
|
79
|
+
max-height: 90vh;
|
|
80
|
+
display: flex;
|
|
81
|
+
align-items: center;
|
|
82
|
+
justify-content: center;
|
|
83
|
+
cursor: default;
|
|
84
|
+
|
|
85
|
+
svg {
|
|
86
|
+
max-width: 90vw;
|
|
87
|
+
max-height: 90vh;
|
|
88
|
+
box-shadow: 0 8px 40px rgba(0, 0, 0, 0.6);
|
|
89
|
+
border-radius: 4px;
|
|
90
|
+
}
|
|
91
|
+
}
|
package/src/svg/svg.ts
ADDED
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
import { html, LitElement } from 'lit';
|
|
2
|
+
import { property, state } from 'lit/decorators.js';
|
|
3
|
+
import { unsafeSVG } from 'lit/directives/unsafe-svg.js';
|
|
4
|
+
|
|
5
|
+
import { sanitizeSvg } from '@/__utils/sanitize-svg.js';
|
|
6
|
+
import { fetchSVG } from '../icon/datasource.js';
|
|
7
|
+
|
|
8
|
+
import styles from './svg.scss';
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* @label SVG
|
|
12
|
+
* @tag wc-svg
|
|
13
|
+
* @rawTag svg
|
|
14
|
+
* @summary An SVG component with lazy loading and optional preview support.
|
|
15
|
+
* @overview Renders an inline SVG fetched from a URL, with lazy loading via IntersectionObserver and an optional click-to-preview lightbox.
|
|
16
|
+
*
|
|
17
|
+
* @cssprop --svg-color - Controls the fill color of the SVG.
|
|
18
|
+
* @cssprop [--svg-size=1rem] - Controls the size of the SVG. Defaults to "1rem"
|
|
19
|
+
*
|
|
20
|
+
* @example
|
|
21
|
+
* ```html
|
|
22
|
+
* <wc-svg src="/icons/my-icon.svg" image-title="My icon"></wc-svg>
|
|
23
|
+
* ```
|
|
24
|
+
*/
|
|
25
|
+
export class Svg extends LitElement {
|
|
26
|
+
static styles = [styles];
|
|
27
|
+
|
|
28
|
+
/** URL of the SVG asset to fetch and render inline. */
|
|
29
|
+
@property({ type: String, reflect: true }) src = '';
|
|
30
|
+
|
|
31
|
+
/** Accessible title / alt text for the SVG. */
|
|
32
|
+
@property({ attribute: 'image-title' }) imageTitle = '';
|
|
33
|
+
|
|
34
|
+
/** Enable click-to-preview lightbox. */
|
|
35
|
+
@property({ type: Boolean, reflect: true }) preview = false;
|
|
36
|
+
|
|
37
|
+
@state() private _loaded = false;
|
|
38
|
+
|
|
39
|
+
@state() private _previewOpen = false;
|
|
40
|
+
|
|
41
|
+
@state() private _svgContent: string = '';
|
|
42
|
+
|
|
43
|
+
// token to avoid stale fetch results
|
|
44
|
+
private _fetchId = 0;
|
|
45
|
+
|
|
46
|
+
private _intersectionObserver: IntersectionObserver | null = null;
|
|
47
|
+
|
|
48
|
+
disconnectedCallback() {
|
|
49
|
+
super.disconnectedCallback();
|
|
50
|
+
this._intersectionObserver?.disconnect();
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
firstUpdated() {
|
|
54
|
+
this._setupIntersectionObserver();
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
updated(changedProperties: Map<string, unknown>) {
|
|
58
|
+
if (changedProperties.has('src')) {
|
|
59
|
+
// Reset lazy-load state so the new src is fetched when visible
|
|
60
|
+
this._loaded = false;
|
|
61
|
+
this._svgContent = '';
|
|
62
|
+
this._setupIntersectionObserver();
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
private _setupIntersectionObserver() {
|
|
67
|
+
this._intersectionObserver?.disconnect();
|
|
68
|
+
|
|
69
|
+
const wrapper = this.shadowRoot?.querySelector('.svg-wrapper');
|
|
70
|
+
if (!wrapper) return;
|
|
71
|
+
|
|
72
|
+
this._intersectionObserver = new IntersectionObserver(
|
|
73
|
+
(entries) => {
|
|
74
|
+
if (entries[0].isIntersecting) {
|
|
75
|
+
this._loaded = true;
|
|
76
|
+
this._intersectionObserver?.disconnect();
|
|
77
|
+
this._fetchSvg();
|
|
78
|
+
}
|
|
79
|
+
},
|
|
80
|
+
{ rootMargin: '200px' },
|
|
81
|
+
);
|
|
82
|
+
|
|
83
|
+
this._intersectionObserver.observe(wrapper);
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
private async _fetchSvg() {
|
|
87
|
+
if (!this.src) return;
|
|
88
|
+
|
|
89
|
+
this._fetchId += 1;
|
|
90
|
+
const currentId = this._fetchId;
|
|
91
|
+
|
|
92
|
+
try {
|
|
93
|
+
const raw = await fetchSVG(this.src);
|
|
94
|
+
if (currentId !== this._fetchId) return;
|
|
95
|
+
|
|
96
|
+
this._svgContent = raw ? sanitizeSvg(raw) : '';
|
|
97
|
+
} catch {
|
|
98
|
+
if (currentId === this._fetchId) {
|
|
99
|
+
this._svgContent = '';
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
private _handleClick() {
|
|
105
|
+
if (this.preview) {
|
|
106
|
+
this._previewOpen = true;
|
|
107
|
+
// Move focus into the dialog after render
|
|
108
|
+
this.updateComplete.then(() => {
|
|
109
|
+
const closeBtn = this.shadowRoot?.querySelector<HTMLElement>('.preview-close');
|
|
110
|
+
closeBtn?.focus();
|
|
111
|
+
});
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
private _closePreview(e: Event) {
|
|
116
|
+
e.stopPropagation();
|
|
117
|
+
const wasOpen = this._previewOpen;
|
|
118
|
+
this._previewOpen = false;
|
|
119
|
+
if (wasOpen) {
|
|
120
|
+
// Return focus to the trigger
|
|
121
|
+
const trigger = this.shadowRoot?.querySelector<HTMLElement>('.svg-content');
|
|
122
|
+
trigger?.focus();
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
render() {
|
|
127
|
+
return html`
|
|
128
|
+
<div class="svg-wrapper">
|
|
129
|
+
${this._loaded && this._svgContent
|
|
130
|
+
? html`<div
|
|
131
|
+
class="svg-content ${this.preview ? 'clickable' : ''}"
|
|
132
|
+
role=${this.imageTitle ? 'img' : 'presentation'}
|
|
133
|
+
aria-label=${this.imageTitle || ''}
|
|
134
|
+
@click=${this._handleClick}
|
|
135
|
+
>
|
|
136
|
+
${unsafeSVG(this._svgContent)}
|
|
137
|
+
</div>`
|
|
138
|
+
: html`<span class="placeholder" aria-hidden="true"></span>`}
|
|
139
|
+
</div>
|
|
140
|
+
|
|
141
|
+
<div
|
|
142
|
+
class="preview-overlay ${this._previewOpen ? 'open' : ''}"
|
|
143
|
+
role="dialog"
|
|
144
|
+
aria-modal="true"
|
|
145
|
+
aria-label=${this.imageTitle ? `Preview: ${this.imageTitle}` : 'SVG preview'}
|
|
146
|
+
@click=${this._closePreview}
|
|
147
|
+
@keydown=${(e: KeyboardEvent) => e.key === 'Escape' && this._closePreview(e)}
|
|
148
|
+
>
|
|
149
|
+
<button
|
|
150
|
+
class="preview-close"
|
|
151
|
+
aria-label="Close preview"
|
|
152
|
+
@click=${this._closePreview}
|
|
153
|
+
>✕</button>
|
|
154
|
+
<div class="preview-content" @click=${(e: Event) => e.stopPropagation()}>
|
|
155
|
+
${unsafeSVG(this._svgContent)}
|
|
156
|
+
</div>
|
|
157
|
+
</div>
|
|
158
|
+
`;
|
|
159
|
+
}
|
|
160
|
+
}
|
package/src/table/table.ts
CHANGED
|
@@ -218,7 +218,7 @@ export class Table extends LitElement {
|
|
|
218
218
|
}
|
|
219
219
|
|
|
220
220
|
private getTotalItems(): number {
|
|
221
|
-
if (this.paginate && !this.managed) return this.data.length;
|
|
221
|
+
if (this.paginate && !this.managed && this.data) return this.data.length;
|
|
222
222
|
return this.totalItems ?? 0;
|
|
223
223
|
}
|
|
224
224
|
|
|
@@ -468,7 +468,7 @@ export class Table extends LitElement {
|
|
|
468
468
|
<div class=${classMap(tableClasses)}>
|
|
469
469
|
<div class="table-scroll-container" @scroll=${this.onScrollContainer}>
|
|
470
470
|
${this.renderHeader()}
|
|
471
|
-
${this.data.length ? this.renderBody() : this.renderEmptyState()}
|
|
471
|
+
${this.data && this.data.length ? this.renderBody() : this.renderEmptyState()}
|
|
472
472
|
</div>
|
|
473
473
|
<div class="table-footer">${this.renderPagination()}</div>
|
|
474
474
|
</div>
|
package/src/toolbar/toolbar.ts
CHANGED
|
@@ -33,10 +33,10 @@ import colorStyles from './toolbar-colors.scss';
|
|
|
33
33
|
* ```html
|
|
34
34
|
* <!-- Docked toolbar -->
|
|
35
35
|
* <wc-toolbar>
|
|
36
|
-
* <wc-icon-button variant="text"><wc-icon name="home"></wc-icon></wc-icon-button>
|
|
36
|
+
* <wc-icon-button variant="text" color="surface"><wc-icon name="home"></wc-icon></wc-icon-button>
|
|
37
37
|
* <wc-icon-button variant="tonal"><wc-icon name="search"></wc-icon></wc-icon-button>
|
|
38
|
-
* <wc-icon-button variant="text"><wc-icon name="favorite"></wc-icon></wc-icon-button>
|
|
39
|
-
* <wc-icon-button variant="text"><wc-icon name="account_circle"></wc-icon></wc-icon-button>
|
|
38
|
+
* <wc-icon-button variant="text" color="surface"><wc-icon name="favorite"></wc-icon></wc-icon-button>
|
|
39
|
+
* <wc-icon-button variant="text" color="surface"><wc-icon name="account_circle"></wc-icon></wc-icon-button>
|
|
40
40
|
* </wc-toolbar>
|
|
41
41
|
* ```
|
|
42
42
|
*
|
package/src/tooltip/tooltip.scss
CHANGED
|
@@ -5,13 +5,14 @@
|
|
|
5
5
|
|
|
6
6
|
|
|
7
7
|
:host(:not([preview])) {
|
|
8
|
+
position: absolute;
|
|
9
|
+
top: 0;
|
|
10
|
+
left: 0;
|
|
11
|
+
|
|
8
12
|
.tooltip {
|
|
9
13
|
pointer-events: none;
|
|
10
14
|
transition: transform var(--duration-short2) ease-in-out, opacity var(--duration-short2) ease-in-out;
|
|
11
15
|
transform: scale(0);
|
|
12
|
-
position: absolute;
|
|
13
|
-
top: 0;
|
|
14
|
-
left: 0;
|
|
15
16
|
opacity: 0;
|
|
16
17
|
}
|
|
17
18
|
|