@redvars/peacock 3.5.1 → 3.6.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.
- 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/condition-builder.js +58 -0
- package/dist/condition-builder.js.map +1 -0
- package/dist/custom-elements-jsdocs.json +7976 -4294
- package/dist/custom-elements.json +14358 -7589
- 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-dZnLJOQT.js +1656 -0
- package/dist/flow-designer-dZnLJOQT.js.map +1 -0
- package/dist/flow-designer-node-XMe-jlKg.js +548 -0
- package/dist/flow-designer-node-XMe-jlKg.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 +358 -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 +418 -0
- package/dist/modal.js.map +1 -0
- package/dist/{navigation-rail-Lxetd5-Z.js → navigation-rail-DyO0oAZU.js} +306 -2197
- package/dist/navigation-rail-DyO0oAZU.js.map +1 -0
- package/dist/notification-manager.js +268 -0
- package/dist/notification-manager.js.map +1 -0
- package/dist/peacock-loader.js +84 -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 +56 -0
- package/dist/src/html-editor/index.d.ts +2 -0
- package/dist/src/index.d.ts +13 -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 +63 -0
- package/dist/src/notification-manager/index.d.ts +1 -0
- package/dist/src/notification-manager/notification-manager.d.ts +44 -0
- 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/tooltip/tooltip.d.ts +2 -15
- package/dist/test/flow-designer.test.d.ts +1 -0
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +4 -2
- package/readme.md +2 -2
- 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/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 +146 -0
- package/src/html-editor/html-editor.ts +276 -0
- package/src/html-editor/index.ts +3 -0
- package/src/index.ts +25 -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 +201 -0
- 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/peacock-loader.ts +71 -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/table/table.ts +2 -2
- 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,276 @@
|
|
|
1
|
+
import { html, nothing } from 'lit';
|
|
2
|
+
import { property, query, state } from 'lit/decorators.js';
|
|
3
|
+
import { classMap } from 'lit/directives/class-map.js';
|
|
4
|
+
|
|
5
|
+
import IndividualComponent from '@/IndividualComponent.js';
|
|
6
|
+
import BaseInput from '../input/BaseInput.js';
|
|
7
|
+
import { redispatchEvent } from '../__utils/dispatch-event-utils.js';
|
|
8
|
+
|
|
9
|
+
import styles from './html-editor.scss';
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* @label HTML Editor
|
|
13
|
+
* @tag wc-html-editor
|
|
14
|
+
* @rawTag html-editor
|
|
15
|
+
*
|
|
16
|
+
* @summary A WYSIWYG HTML editor component with a Material 3 styled toolbar.
|
|
17
|
+
* @overview
|
|
18
|
+
* <p>The HTML Editor provides a rich-text editing experience using the browser's built-in
|
|
19
|
+
* <code>contenteditable</code> API. It wraps the editable area in a Material 3 styled
|
|
20
|
+
* <code>wc-field</code> and exposes a toolbar with common formatting actions.</p>
|
|
21
|
+
*
|
|
22
|
+
* <p>Get and set the HTML content via the <code>value</code> property. The component
|
|
23
|
+
* dispatches a <code>change</code> event whenever the content is modified.</p>
|
|
24
|
+
*
|
|
25
|
+
* @cssprop --html-editor-min-height - Minimum height of the editable area. Defaults to 8rem.
|
|
26
|
+
* @cssprop --html-editor-toolbar-background - Background color of the toolbar.
|
|
27
|
+
* @cssprop --html-editor-toolbar-border-color - Border color between toolbar and editing area.
|
|
28
|
+
*
|
|
29
|
+
* @fires {Event} change - Fired whenever the editable content changes.
|
|
30
|
+
*
|
|
31
|
+
* @example
|
|
32
|
+
* ```html
|
|
33
|
+
* <wc-html-editor label="Description" value="<p>Hello <strong>world</strong></p>"></wc-html-editor>
|
|
34
|
+
* ```
|
|
35
|
+
* @tags input editor
|
|
36
|
+
*/
|
|
37
|
+
@IndividualComponent
|
|
38
|
+
export class HtmlEditor extends BaseInput {
|
|
39
|
+
static styles = [styles];
|
|
40
|
+
|
|
41
|
+
/** Current HTML value of the editor. */
|
|
42
|
+
@property({ type: String })
|
|
43
|
+
value = '';
|
|
44
|
+
|
|
45
|
+
/** Label displayed above the editor. */
|
|
46
|
+
@property({ type: String })
|
|
47
|
+
label = '';
|
|
48
|
+
|
|
49
|
+
/** Placeholder text shown when the editor is empty. */
|
|
50
|
+
@property({ type: String })
|
|
51
|
+
placeholder = 'Enter text\u2026';
|
|
52
|
+
|
|
53
|
+
/** Visual style of the wrapping field. */
|
|
54
|
+
@property({ type: String })
|
|
55
|
+
variant: 'filled' | 'outlined' | 'default' = 'default';
|
|
56
|
+
|
|
57
|
+
/** Helper text displayed below the editor. */
|
|
58
|
+
@property({ type: String, attribute: 'helper-text' })
|
|
59
|
+
helperText = '';
|
|
60
|
+
|
|
61
|
+
/** Whether to show an error state. */
|
|
62
|
+
@property({ type: Boolean })
|
|
63
|
+
error = false;
|
|
64
|
+
|
|
65
|
+
/** Error message text. */
|
|
66
|
+
@property({ type: String, attribute: 'error-text' })
|
|
67
|
+
errorText = '';
|
|
68
|
+
|
|
69
|
+
@state() private _focused = false;
|
|
70
|
+
|
|
71
|
+
@query('.html-editor-content')
|
|
72
|
+
private _editorEl!: HTMLDivElement;
|
|
73
|
+
|
|
74
|
+
// ─── Lifecycle ─────────────────────────────────────────────────────────────
|
|
75
|
+
|
|
76
|
+
protected firstUpdated() {
|
|
77
|
+
if (this.value && this._editorEl) {
|
|
78
|
+
this._editorEl.innerHTML = this.value;
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
protected updated(changed: Map<string, unknown>) {
|
|
83
|
+
if (changed.has('value') && this._editorEl) {
|
|
84
|
+
if (this._editorEl.innerHTML !== this.value) {
|
|
85
|
+
this._editorEl.innerHTML = this.value ?? '';
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
if (changed.has('disabled') || changed.has('readonly')) {
|
|
89
|
+
if (this._editorEl) {
|
|
90
|
+
this._editorEl.contentEditable =
|
|
91
|
+
this.disabled || this.readonly ? 'false' : 'true';
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
// ─── Private helpers ───────────────────────────────────────────────────────
|
|
97
|
+
|
|
98
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
99
|
+
private _execCmd(command: string, value?: string) {
|
|
100
|
+
if (this.disabled || this.readonly) return;
|
|
101
|
+
this._editorEl.focus();
|
|
102
|
+
// execCommand is deprecated but remains broadly supported for rich-text editing
|
|
103
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
104
|
+
(document as any).execCommand(command, false, value ?? null);
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
private _handleInput() {
|
|
108
|
+
this.value = this._editorEl.innerHTML;
|
|
109
|
+
redispatchEvent(
|
|
110
|
+
this,
|
|
111
|
+
new Event('change', { bubbles: true, composed: true }),
|
|
112
|
+
);
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
private _handleFocus() {
|
|
116
|
+
this._focused = true;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
private _handleBlur() {
|
|
120
|
+
this._focused = false;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
private _insertLink() {
|
|
124
|
+
// eslint-disable-next-line no-alert
|
|
125
|
+
const url = window.prompt('Enter URL:', 'https://');
|
|
126
|
+
if (url) this._execCmd('createLink', url);
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
// ─── Toolbar button ────────────────────────────────────────────────────────
|
|
130
|
+
|
|
131
|
+
private _toolbarButton(
|
|
132
|
+
icon: string,
|
|
133
|
+
title: string,
|
|
134
|
+
command: string,
|
|
135
|
+
value?: string,
|
|
136
|
+
) {
|
|
137
|
+
return html`
|
|
138
|
+
<button
|
|
139
|
+
class="toolbar-btn"
|
|
140
|
+
title=${title}
|
|
141
|
+
aria-label=${title}
|
|
142
|
+
?disabled=${this.disabled || this.readonly}
|
|
143
|
+
@mousedown=${(e: Event) => e.preventDefault()}
|
|
144
|
+
@click=${(e: Event) => {
|
|
145
|
+
e.preventDefault();
|
|
146
|
+
this._execCmd(command, value);
|
|
147
|
+
}}
|
|
148
|
+
>
|
|
149
|
+
<wc-icon name=${icon} size="sm"></wc-icon>
|
|
150
|
+
</button>
|
|
151
|
+
`;
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
// ─── Toolbar ───────────────────────────────────────────────────────────────
|
|
155
|
+
|
|
156
|
+
private _renderToolbar() {
|
|
157
|
+
return html`
|
|
158
|
+
<div
|
|
159
|
+
class="html-editor-toolbar"
|
|
160
|
+
role="toolbar"
|
|
161
|
+
aria-label="Formatting toolbar"
|
|
162
|
+
>
|
|
163
|
+
${this._toolbarButton('format_bold', 'Bold', 'bold')}
|
|
164
|
+
${this._toolbarButton('format_italic', 'Italic', 'italic')}
|
|
165
|
+
${this._toolbarButton('format_underlined', 'Underline', 'underline')}
|
|
166
|
+
${this._toolbarButton(
|
|
167
|
+
'format_strikethrough',
|
|
168
|
+
'Strikethrough',
|
|
169
|
+
'strikeThrough',
|
|
170
|
+
)}
|
|
171
|
+
|
|
172
|
+
<span class="toolbar-divider"></span>
|
|
173
|
+
|
|
174
|
+
${this._toolbarButton('format_align_left', 'Align left', 'justifyLeft')}
|
|
175
|
+
${this._toolbarButton(
|
|
176
|
+
'format_align_center',
|
|
177
|
+
'Align center',
|
|
178
|
+
'justifyCenter',
|
|
179
|
+
)}
|
|
180
|
+
${this._toolbarButton(
|
|
181
|
+
'format_align_right',
|
|
182
|
+
'Align right',
|
|
183
|
+
'justifyRight',
|
|
184
|
+
)}
|
|
185
|
+
|
|
186
|
+
<span class="toolbar-divider"></span>
|
|
187
|
+
|
|
188
|
+
${this._toolbarButton(
|
|
189
|
+
'format_list_bulleted',
|
|
190
|
+
'Unordered list',
|
|
191
|
+
'insertUnorderedList',
|
|
192
|
+
)}
|
|
193
|
+
${this._toolbarButton(
|
|
194
|
+
'format_list_numbered',
|
|
195
|
+
'Ordered list',
|
|
196
|
+
'insertOrderedList',
|
|
197
|
+
)}
|
|
198
|
+
|
|
199
|
+
<span class="toolbar-divider"></span>
|
|
200
|
+
|
|
201
|
+
${this._toolbarButton(
|
|
202
|
+
'format_indent_increase',
|
|
203
|
+
'Indent',
|
|
204
|
+
'indent',
|
|
205
|
+
)}
|
|
206
|
+
${this._toolbarButton('format_indent_decrease', 'Outdent', 'outdent')}
|
|
207
|
+
|
|
208
|
+
<span class="toolbar-divider"></span>
|
|
209
|
+
|
|
210
|
+
<button
|
|
211
|
+
class="toolbar-btn"
|
|
212
|
+
title="Insert link"
|
|
213
|
+
aria-label="Insert link"
|
|
214
|
+
?disabled=${this.disabled || this.readonly}
|
|
215
|
+
@mousedown=${(e: Event) => e.preventDefault()}
|
|
216
|
+
@click=${() => this._insertLink()}
|
|
217
|
+
>
|
|
218
|
+
<wc-icon name="link" size="sm"></wc-icon>
|
|
219
|
+
</button>
|
|
220
|
+
|
|
221
|
+
<span class="toolbar-divider"></span>
|
|
222
|
+
|
|
223
|
+
${this._toolbarButton('undo', 'Undo', 'undo')}
|
|
224
|
+
${this._toolbarButton('redo', 'Redo', 'redo')}
|
|
225
|
+
</div>
|
|
226
|
+
`;
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
// ─── Render ────────────────────────────────────────────────────────────────
|
|
230
|
+
|
|
231
|
+
render() {
|
|
232
|
+
const isEmpty = !this.value || this.value === '<br>';
|
|
233
|
+
|
|
234
|
+
return html`
|
|
235
|
+
<wc-field
|
|
236
|
+
label=${this.label}
|
|
237
|
+
?required=${this.required}
|
|
238
|
+
?disabled=${this.disabled}
|
|
239
|
+
?readonly=${this.readonly}
|
|
240
|
+
?skeleton=${this.skeleton}
|
|
241
|
+
?focused=${this._focused}
|
|
242
|
+
?error=${this.error}
|
|
243
|
+
error-text=${this.errorText}
|
|
244
|
+
helper-text=${this.helperText}
|
|
245
|
+
variant=${this.variant}
|
|
246
|
+
?populated=${!isEmpty}
|
|
247
|
+
.host=${this}
|
|
248
|
+
class=${classMap({
|
|
249
|
+
'html-editor-field': true,
|
|
250
|
+
disabled: this.disabled,
|
|
251
|
+
readonly: this.readonly,
|
|
252
|
+
})}
|
|
253
|
+
>
|
|
254
|
+
${this._renderToolbar()}
|
|
255
|
+
|
|
256
|
+
<div
|
|
257
|
+
class=${classMap({
|
|
258
|
+
'html-editor-content': true,
|
|
259
|
+
'is-empty': isEmpty,
|
|
260
|
+
})}
|
|
261
|
+
contenteditable=${this.disabled || this.readonly ? 'false' : 'true'}
|
|
262
|
+
data-placeholder=${this.placeholder}
|
|
263
|
+
@input=${this._handleInput}
|
|
264
|
+
@focus=${this._handleFocus}
|
|
265
|
+
@blur=${this._handleBlur}
|
|
266
|
+
></div>
|
|
267
|
+
|
|
268
|
+
${this.disabled
|
|
269
|
+
? html`<wc-tag class="read-only-tag" color="red">Disabled</wc-tag>`
|
|
270
|
+
: this.readonly
|
|
271
|
+
? html`<wc-tag class="read-only-tag" color="red">Read Only</wc-tag>`
|
|
272
|
+
: nothing}
|
|
273
|
+
</wc-field>
|
|
274
|
+
`;
|
|
275
|
+
}
|
|
276
|
+
}
|
package/src/index.ts
CHANGED
|
@@ -7,6 +7,8 @@ export { Elevation } from './elevation/index.js';
|
|
|
7
7
|
export { Button, ButtonGroup, IconButton } from './button/index.js';
|
|
8
8
|
export { Fab } from './fab/index.js';
|
|
9
9
|
export { SegmentedButton, SegmentedButtonGroup } from './segmented-button/index.js';
|
|
10
|
+
export { SplitButton } from './split-button/index.js';
|
|
11
|
+
export { DropdownButton } from './dropdown-button/index.js';
|
|
10
12
|
|
|
11
13
|
export { FocusRing } from './focus-ring/index.js';
|
|
12
14
|
export { Ripple } from './ripple/index.js';
|
|
@@ -32,11 +34,13 @@ export { Container } from './container/index.js';
|
|
|
32
34
|
export { NumberCounter } from './number-counter/index.js';
|
|
33
35
|
export { EmptyState } from './empty-state/index.js';
|
|
34
36
|
export { Tooltip } from './popover/index.js';
|
|
37
|
+
export { Popover, PopoverContent } from './popover/index.js';
|
|
35
38
|
export { Breadcrumb, BreadcrumbItem } from './breadcrumb/index.js';
|
|
36
39
|
export { Menu, MenuItem, SubMenu } from './menu/index.js';
|
|
37
40
|
|
|
38
41
|
export { CodeHighlighter } from './code-highlighter/index.js';
|
|
39
42
|
export { CodeEditor } from './code-editor/index.js';
|
|
43
|
+
export { HtmlEditor } from './html-editor/index.js';
|
|
40
44
|
export { Image } from './image/index.js';
|
|
41
45
|
export { Tab, TabGroup, TabPanel, Tabs } from './tabs/index.js';
|
|
42
46
|
export { Slider } from './slider/index.js';
|
|
@@ -49,8 +53,10 @@ export { SidebarMenu, SidebarMenuItem, SidebarSubMenu } from './sidebar-menu/ind
|
|
|
49
53
|
export { Card } from './card/index.js';
|
|
50
54
|
export { Banner } from './banner/index.js';
|
|
51
55
|
export { Notification } from './notification/index.js';
|
|
56
|
+
export { NotificationManager } from './notification-manager/index.js';
|
|
52
57
|
export { Snackbar } from './snackbar/index.js';
|
|
53
58
|
export { Radio } from './radio/index.js';
|
|
59
|
+
export { Modal } from './modal/index.js';
|
|
54
60
|
export { BottomSheet } from './bottom-sheet/index.js';
|
|
55
61
|
export { SideSheet } from './side-sheet/index.js';
|
|
56
62
|
export { Select } from './select/index.js';
|
|
@@ -59,4 +65,23 @@ export { SelectOptionElement } from './select/index.js';
|
|
|
59
65
|
export { Search } from './search/index.js';
|
|
60
66
|
export { Toolbar } from './toolbar/index.js';
|
|
61
67
|
export { NavigationRail, NavigationRailItem } from './navigation-rail/index.js';
|
|
68
|
+
export { Calendar, CalendarColumnView, CalendarMonthView } from './calendar/index.js';
|
|
69
|
+
export type { CalendarViewType, EventType } from './calendar/index.js';
|
|
70
|
+
export { Canvas } from './canvas/index.js';
|
|
71
|
+
export type { CanvasShape } from './canvas/index.js';
|
|
72
|
+
export { FlowDesigner, FlowDesignerNode } from './flow-designer/index.js';
|
|
73
|
+
export type {
|
|
74
|
+
Workflow,
|
|
75
|
+
WorkflowNode,
|
|
76
|
+
WorkflowCommand,
|
|
77
|
+
PositionedNode,
|
|
78
|
+
ValidationError,
|
|
79
|
+
HistoryEntry,
|
|
80
|
+
EditorState,
|
|
81
|
+
NodeType,
|
|
82
|
+
WorkflowChangeEvent,
|
|
83
|
+
SwimlaneConfig,
|
|
84
|
+
NodeTemplate,
|
|
85
|
+
} from './flow-designer/index.js';
|
|
86
|
+
export { ConditionBuilder, CbPredicate, CbCompoundExpression, CbExpression, CbDivider } from './condition-builder/index.js';
|
|
62
87
|
|
package/src/menu/menu/menu.scss
CHANGED
|
@@ -12,8 +12,8 @@
|
|
|
12
12
|
padding-block: var(--spacing-050);
|
|
13
13
|
transform-origin: top center;
|
|
14
14
|
|
|
15
|
-
--_menu-enter-duration: var(--duration-medium1
|
|
16
|
-
--_menu-exit-duration: var(--duration-
|
|
15
|
+
--_menu-enter-duration: var(--duration-medium1);
|
|
16
|
+
--_menu-exit-duration: var(--duration-medium2);
|
|
17
17
|
--_menu-enter-easing: cubic-bezier(0.05, 0.7, 0.1, 1);
|
|
18
18
|
--_menu-exit-easing: cubic-bezier(0.3, 0, 0.8, 0.15);
|
|
19
19
|
|
package/src/menu/menu/menu.ts
CHANGED
|
@@ -3,8 +3,8 @@ import { property, query, state } from 'lit/decorators.js';
|
|
|
3
3
|
import { classMap } from 'lit/directives/class-map.js';
|
|
4
4
|
import type { Placement } from '@floating-ui/dom';
|
|
5
5
|
import styles from './menu.scss';
|
|
6
|
+
import { FloatingController } from '../../__controllers/floating-controller.js';
|
|
6
7
|
import { MenuItem } from '../menu-item/menu-item.js';
|
|
7
|
-
import { MenuSurfaceController } from './MenuSurfaceController.js';
|
|
8
8
|
|
|
9
9
|
type CloseReason =
|
|
10
10
|
| { kind: 'click-selection' }
|
|
@@ -60,7 +60,18 @@ export class Menu extends LitElement {
|
|
|
60
60
|
|
|
61
61
|
anchorElement: HTMLElement | null = null;
|
|
62
62
|
|
|
63
|
-
private readonly
|
|
63
|
+
private readonly _floatingController = new FloatingController(this, {
|
|
64
|
+
trigger: 'manual',
|
|
65
|
+
closeOnClickOutside: false,
|
|
66
|
+
strategy: 'fixed',
|
|
67
|
+
onOpenChange: (isOpen) => {
|
|
68
|
+
if (isOpen || !this.open) {
|
|
69
|
+
return;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
this.close({ kind: 'outside-click' });
|
|
73
|
+
},
|
|
74
|
+
});
|
|
64
75
|
|
|
65
76
|
private _lastFocusedElement: HTMLElement | null = null;
|
|
66
77
|
|
|
@@ -72,22 +83,14 @@ export class Menu extends LitElement {
|
|
|
72
83
|
this.setAttribute('role', 'menu');
|
|
73
84
|
|
|
74
85
|
this.addEventListener('keydown', this._onKeyDown);
|
|
75
|
-
this.addEventListener('
|
|
76
|
-
this.addEventListener('menu-item-activate', this._onItemActivate);
|
|
77
|
-
this.addEventListener('menu-item-request-close', this._onItemRequestClose);
|
|
78
|
-
window.addEventListener('click', this._onWindowClick, { capture: true });
|
|
86
|
+
this.addEventListener('click', this._onClick);
|
|
79
87
|
this._syncAnchorAria();
|
|
80
88
|
}
|
|
81
89
|
|
|
82
90
|
disconnectedCallback() {
|
|
83
91
|
this.removeEventListener('keydown', this._onKeyDown);
|
|
84
|
-
this.removeEventListener('
|
|
85
|
-
this.
|
|
86
|
-
this.removeEventListener(
|
|
87
|
-
'menu-item-request-close',
|
|
88
|
-
this._onItemRequestClose,
|
|
89
|
-
);
|
|
90
|
-
window.removeEventListener('click', this._onWindowClick, { capture: true });
|
|
92
|
+
this.removeEventListener('click', this._onClick);
|
|
93
|
+
this._floatingController.close();
|
|
91
94
|
super.disconnectedCallback();
|
|
92
95
|
}
|
|
93
96
|
|
|
@@ -170,7 +173,12 @@ export class Menu extends LitElement {
|
|
|
170
173
|
}
|
|
171
174
|
|
|
172
175
|
private _syncRovingTabIndex() {
|
|
176
|
+
const ownedItems = this.items;
|
|
173
177
|
const enabledItems = this._enabledItems();
|
|
178
|
+
for (const item of ownedItems) {
|
|
179
|
+
item.tabIndex = -1;
|
|
180
|
+
}
|
|
181
|
+
|
|
174
182
|
if (!enabledItems.length) {
|
|
175
183
|
this.activeIndex = -1;
|
|
176
184
|
return;
|
|
@@ -180,10 +188,7 @@ export class Menu extends LitElement {
|
|
|
180
188
|
this.activeIndex = 0;
|
|
181
189
|
}
|
|
182
190
|
|
|
183
|
-
|
|
184
|
-
const currentItem = enabledItems[index];
|
|
185
|
-
currentItem.tabIndex = index === this.activeIndex ? 0 : -1;
|
|
186
|
-
}
|
|
191
|
+
enabledItems[this.activeIndex].tabIndex = 0;
|
|
187
192
|
}
|
|
188
193
|
|
|
189
194
|
private _setActiveByOffset(offset: 1 | -1) {
|
|
@@ -227,50 +232,66 @@ export class Menu extends LitElement {
|
|
|
227
232
|
return this._enabledItems()[0] ?? null;
|
|
228
233
|
}
|
|
229
234
|
|
|
230
|
-
private
|
|
235
|
+
private _isEventFromThisMenu(event: Event) {
|
|
231
236
|
const path = event.composedPath();
|
|
232
|
-
const
|
|
237
|
+
const sourceMenu = path.find(
|
|
238
|
+
target =>
|
|
239
|
+
target instanceof HTMLElement &&
|
|
240
|
+
target.tagName.toLowerCase() === 'wc-menu',
|
|
241
|
+
);
|
|
233
242
|
|
|
234
|
-
return
|
|
243
|
+
return sourceMenu === this;
|
|
235
244
|
}
|
|
236
245
|
|
|
237
|
-
private
|
|
238
|
-
|
|
239
|
-
|
|
246
|
+
private _ownedItemFromEvent(event: Event) {
|
|
247
|
+
if (!this._isEventFromThisMenu(event)) {
|
|
248
|
+
return null;
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
const path = event.composedPath();
|
|
240
252
|
const ownedItems = this.items;
|
|
241
|
-
|
|
242
|
-
|
|
253
|
+
|
|
254
|
+
for (const target of path) {
|
|
255
|
+
if (target instanceof HTMLElement) {
|
|
256
|
+
if (target.tagName.toLowerCase() === 'wc-menu-item') {
|
|
257
|
+
const ownedItem = ownedItems.find(item => item === target);
|
|
258
|
+
if (ownedItem) {
|
|
259
|
+
return ownedItem;
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
}
|
|
243
263
|
}
|
|
244
264
|
|
|
265
|
+
return null;
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
private _setActiveItem(item: MenuItem) {
|
|
245
269
|
const enabledItems = this._enabledItems();
|
|
246
270
|
const nextIndex = enabledItems.indexOf(item);
|
|
247
|
-
if (nextIndex
|
|
248
|
-
|
|
249
|
-
this._syncRovingTabIndex();
|
|
271
|
+
if (nextIndex < 0) {
|
|
272
|
+
return;
|
|
250
273
|
}
|
|
251
|
-
};
|
|
252
274
|
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
reason: 'click-selection' | 'keydown';
|
|
257
|
-
key?: string;
|
|
258
|
-
}>;
|
|
275
|
+
this.activeIndex = nextIndex;
|
|
276
|
+
this._syncRovingTabIndex();
|
|
277
|
+
}
|
|
259
278
|
|
|
260
|
-
|
|
279
|
+
private _onClick = (event: Event) => {
|
|
280
|
+
if (!this.open) {
|
|
261
281
|
return;
|
|
262
282
|
}
|
|
263
283
|
|
|
264
|
-
|
|
284
|
+
const item = this._ownedItemFromEvent(event);
|
|
285
|
+
if (!item) {
|
|
265
286
|
return;
|
|
266
287
|
}
|
|
267
288
|
|
|
268
|
-
|
|
269
|
-
|
|
289
|
+
this._setActiveItem(item);
|
|
290
|
+
if (item.keepOpen) {
|
|
270
291
|
return;
|
|
271
292
|
}
|
|
272
293
|
|
|
273
|
-
this.close({ kind: '
|
|
294
|
+
this.close({ kind: 'click-selection' });
|
|
274
295
|
};
|
|
275
296
|
|
|
276
297
|
private _onKeyDown = (event: KeyboardEvent) => {
|
|
@@ -278,10 +299,15 @@ export class Menu extends LitElement {
|
|
|
278
299
|
return;
|
|
279
300
|
}
|
|
280
301
|
|
|
281
|
-
if (!this.
|
|
302
|
+
if (!this._isEventFromThisMenu(event)) {
|
|
282
303
|
return;
|
|
283
304
|
}
|
|
284
305
|
|
|
306
|
+
const eventItem = this._ownedItemFromEvent(event);
|
|
307
|
+
if (eventItem) {
|
|
308
|
+
this._setActiveItem(eventItem);
|
|
309
|
+
}
|
|
310
|
+
|
|
285
311
|
switch (event.key) {
|
|
286
312
|
case 'ArrowDown':
|
|
287
313
|
event.preventDefault();
|
|
@@ -305,67 +331,27 @@ export class Menu extends LitElement {
|
|
|
305
331
|
event.preventDefault();
|
|
306
332
|
this.close({ kind: 'keydown', key: 'Escape' });
|
|
307
333
|
break;
|
|
308
|
-
|
|
334
|
+
case 'Tab':
|
|
335
|
+
this.close({ kind: 'keydown', key: 'Tab' });
|
|
309
336
|
break;
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
const path = event.composedPath();
|
|
319
|
-
const anchorEl = this._resolveAnchorElement();
|
|
320
|
-
const inMenuTree = path.some(
|
|
321
|
-
target => target === this || (target instanceof Node && this.contains(target)),
|
|
322
|
-
);
|
|
323
|
-
|
|
324
|
-
if (inMenuTree || (anchorEl && path.includes(anchorEl))) {
|
|
325
|
-
return;
|
|
326
|
-
}
|
|
327
|
-
|
|
328
|
-
this.close({ kind: 'outside-click' });
|
|
329
|
-
};
|
|
330
|
-
|
|
331
|
-
private _isWithinMenuTree(node: Node | null) {
|
|
332
|
-
if (!node) {
|
|
333
|
-
return false;
|
|
334
|
-
}
|
|
335
|
-
|
|
336
|
-
let current: Node | null = node;
|
|
337
|
-
while (current) {
|
|
338
|
-
if (current === this || this.contains(current)) {
|
|
339
|
-
return true;
|
|
340
|
-
}
|
|
337
|
+
case 'Enter':
|
|
338
|
+
case ' ': {
|
|
339
|
+
event.preventDefault();
|
|
340
|
+
const activeItem = this._getActiveItem() ?? this._getFirstEnabledItem();
|
|
341
|
+
if (!activeItem) {
|
|
342
|
+
return;
|
|
343
|
+
}
|
|
341
344
|
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
} else {
|
|
346
|
-
current = null;
|
|
345
|
+
this._setActiveItem(activeItem);
|
|
346
|
+
activeItem.click();
|
|
347
|
+
break;
|
|
347
348
|
}
|
|
349
|
+
default:
|
|
350
|
+
break;
|
|
348
351
|
}
|
|
352
|
+
};
|
|
349
353
|
|
|
350
|
-
return false;
|
|
351
|
-
}
|
|
352
|
-
|
|
353
|
-
private _onFocusOut = (event: FocusEvent) => {
|
|
354
|
-
if (!this.open || this.stayOpenOnFocusout) {
|
|
355
|
-
return;
|
|
356
|
-
}
|
|
357
|
-
|
|
358
|
-
const next = event.relatedTarget;
|
|
359
|
-
if (!next) {
|
|
360
|
-
return;
|
|
361
|
-
}
|
|
362
|
-
|
|
363
|
-
if (next instanceof Node && this._isWithinMenuTree(next)) {
|
|
364
|
-
return;
|
|
365
|
-
}
|
|
366
354
|
|
|
367
|
-
this.close({ kind: 'focusout' });
|
|
368
|
-
};
|
|
369
355
|
|
|
370
356
|
private _onSlotChange = () => {
|
|
371
357
|
this._syncRovingTabIndex();
|
|
@@ -381,13 +367,14 @@ export class Menu extends LitElement {
|
|
|
381
367
|
return;
|
|
382
368
|
}
|
|
383
369
|
|
|
384
|
-
this.
|
|
385
|
-
reference: anchorEl,
|
|
386
|
-
floating: this.menuListElement,
|
|
370
|
+
this._floatingController.setOptions({
|
|
387
371
|
placement: this.placement,
|
|
388
372
|
offset: this.offset,
|
|
389
373
|
strategy: 'fixed',
|
|
374
|
+
closeOnClickOutside: !this.stayOpenOnOutsideClick,
|
|
390
375
|
});
|
|
376
|
+
this._floatingController.setElements(anchorEl, this.menuListElement);
|
|
377
|
+
this._floatingController.open();
|
|
391
378
|
}
|
|
392
379
|
|
|
393
380
|
protected override updated(changedProperties: Map<string, unknown>) {
|
|
@@ -408,7 +395,7 @@ export class Menu extends LitElement {
|
|
|
408
395
|
|
|
409
396
|
this._applyPositioning();
|
|
410
397
|
} else {
|
|
411
|
-
this.
|
|
398
|
+
this._floatingController.close();
|
|
412
399
|
|
|
413
400
|
const reason = this._closeReason;
|
|
414
401
|
this.dispatchEvent(
|
|
@@ -429,7 +416,10 @@ export class Menu extends LitElement {
|
|
|
429
416
|
}),
|
|
430
417
|
);
|
|
431
418
|
|
|
432
|
-
|
|
419
|
+
const shouldRestoreFocus =
|
|
420
|
+
reason.kind !== 'keydown' || reason.key !== 'Tab';
|
|
421
|
+
|
|
422
|
+
if (!this.isSubmenu && shouldRestoreFocus) {
|
|
433
423
|
this._lastFocusedElement?.focus();
|
|
434
424
|
}
|
|
435
425
|
}
|
|
@@ -92,6 +92,10 @@
|
|
|
92
92
|
--_container-state-opacity: 0.08;
|
|
93
93
|
}
|
|
94
94
|
|
|
95
|
+
&.pressed:not(:where(.disabled)) {
|
|
96
|
+
--_container-state-opacity: 0.12;
|
|
97
|
+
}
|
|
98
|
+
|
|
95
99
|
&.selected {
|
|
96
100
|
--_container-color: var(--menu-item-container-selected-color);
|
|
97
101
|
--_label-text-color: var(--menu-item-label-selected-color);
|