@vollowx/seele 0.13.0 → 0.13.2
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/README.md +6 -66
- package/package.json +2 -1
- package/src/all.js +2 -0
- package/src/base/autocomplete.js +1 -4
- package/src/base/input.js +2 -40
- package/src/base/list.js +1 -1
- package/src/base/menu.js +1 -9
- package/src/base/select.js +1 -1
- package/src/base/slider.js +2 -23
- package/src/base/tabs.js +1 -5
- package/src/m3/autocomplete/autocomplete-styles.css.js +1 -1
- package/src/m3/autocomplete/autocomplete.js +1 -20
- package/src/m3/badge/badge-styles.css.js +1 -1
- package/src/m3/badge/badge.js +1 -6
- package/src/m3/button/common-button-styles.css.js +1 -1
- package/src/m3/button/common-button-toggle.js +1 -9
- package/src/m3/button/common-button.js +1 -7
- package/src/m3/button/icon-button-styles.css.js +1 -1
- package/src/m3/button/icon-button-toggle.js +1 -7
- package/src/m3/button/icon-button.js +1 -6
- package/src/m3/button/shared-button-styles.css.js +1 -1
- package/src/m3/button/shared-button-toggle-styles.css.js +1 -1
- package/src/m3/button-group/standard-button-group-styles.css.js +2 -0
- package/src/m3/button-group/standard-button-group.js +130 -0
- package/src/m3/checkbox/checkbox-styles.css.js +1 -1
- package/src/m3/checkbox/checkbox.js +2 -12
- package/src/m3/dialog/dialog-styles.css.js +1 -1
- package/src/m3/dialog/dialog.js +38 -43
- package/src/m3/divider/divider-styles.css.js +1 -1
- package/src/m3/fab/fab-styles.css.js +1 -1
- package/src/m3/fab/fab.js +1 -7
- package/src/m3/field/field-styles.css.js +1 -1
- package/src/m3/field/field.js +3 -16
- package/src/m3/field/filled-field-styles.css.js +1 -1
- package/src/m3/field/filled-field.js +1 -15
- package/src/m3/field/outlined-field-styles.css.js +1 -1
- package/src/m3/field/outlined-field.js +2 -18
- package/src/m3/focus-ring/focus-ring-styles.css.js +1 -1
- package/src/m3/item/item.js +1 -12
- package/src/m3/list/list-item.js +1 -18
- package/src/m3/loading-indicator/loading-indicator.js +1 -5
- package/src/m3/menu/menu-styles.css.js +1 -1
- package/src/m3/ripple/ripple-styles.css.js +1 -1
- package/src/m3/select/filled-select.js +1 -26
- package/src/m3/select/outlined-select.js +1 -26
- package/src/m3/select/select-styles.css.js +1 -1
- package/src/m3/select/select.js +1 -22
- package/src/m3/slider/slider-styles.css.js +1 -1
- package/src/m3/slider/slider.js +5 -38
- package/src/m3/switch/switch-styles.css.js +1 -1
- package/src/m3/switch/switch.js +3 -22
- package/src/m3/tab/tab-styles.css.js +1 -1
- package/src/m3/tab/tab.js +1 -9
- package/src/m3/tab/tabs-styles.css.js +1 -1
- package/src/m3/tab/tabs.js +1 -4
- package/src/m3/text-field/filled-text-field.js +1 -12
- package/src/m3/text-field/outlined-text-field.js +1 -14
- package/src/m3/text-field/text-field-styles.css.js +1 -1
- package/src/m3/toolbar/toolbar-styles.css.js +1 -1
- package/src/m3/toolbar/toolbar.js +1 -8
- package/src/m3/tooltip/tooltip-styles.css.js +1 -1
- package/src/win98/button/button.js +1 -3
package/README.md
CHANGED
|
@@ -31,74 +31,14 @@ What's the differences comparing to other projects?
|
|
|
31
31
|
meaning that its size is relatively small and the compatibility is not the
|
|
32
32
|
best
|
|
33
33
|
|
|
34
|
-
##
|
|
34
|
+
## Getting started
|
|
35
35
|
|
|
36
|
-
|
|
37
|
-
install with your preferred package manager like
|
|
38
|
-
|
|
39
|
-
```sh
|
|
40
|
-
npm install @vollowx/seele
|
|
41
|
-
```
|
|
42
|
-
|
|
43
|
-
## Quickstart
|
|
44
|
-
|
|
45
|
-
### Importing
|
|
46
|
-
|
|
47
|
-
You can import the entire library or import as needed.
|
|
48
|
-
|
|
49
|
-
```javascript
|
|
50
|
-
// Import all components
|
|
51
|
-
import '@vollowx/seele';
|
|
52
|
-
|
|
53
|
-
// Or import specific components (recommended)
|
|
54
|
-
// They all follow such path: @/catagory/group/component.js
|
|
55
|
-
import '@vollowx/seele/m3/button/common-button.js';
|
|
56
|
-
import '@vollowx/seele/m3/checkbox/checkbox.js';
|
|
57
|
-
|
|
58
|
-
import '@vollowx/seele/win98/button/button.js';
|
|
59
|
-
```
|
|
60
|
-
|
|
61
|
-
### Using
|
|
62
|
-
|
|
63
|
-
Once imported, the components can be used just like standard HTML elements.
|
|
64
|
-
|
|
65
|
-
```html
|
|
66
|
-
<md-button variant="filled">Filled Button</md-button>
|
|
67
|
-
<md-button variant="outlined">Outlined Button</md-button>
|
|
68
|
-
|
|
69
|
-
<label>
|
|
70
|
-
<md-checkbox checked></md-checkbox>
|
|
71
|
-
Labelled Checkbox
|
|
72
|
-
</label>
|
|
73
|
-
|
|
74
|
-
<win98-button>Look old?</win98-button>
|
|
75
|
-
```
|
|
76
|
-
|
|
77
|
-
### Theming
|
|
78
|
-
|
|
79
|
-
seele components use CSS variables for styling. To include the systems for
|
|
80
|
-
Material You Expressive ones, add this to your style files.
|
|
81
|
-
|
|
82
|
-
```css
|
|
83
|
-
@import '@vollowx/seele/m3/systems/base.css';
|
|
84
|
-
/* This includes basic system variables including elevation system and
|
|
85
|
-
typography system */
|
|
86
|
-
@import '@vollowx/seele/m3/systems/defaults.css';
|
|
87
|
-
/* (Optional) This includes basic styling for body, selection and links */
|
|
88
|
-
```
|
|
89
|
-
|
|
90
|
-
Note that there is no default color system and motion physics system to
|
|
91
|
-
have more flexibility and reduce redundant code.
|
|
92
|
-
|
|
93
|
-
For the color system, you can use the official
|
|
94
|
-
[Material Theme Builder](https://material-foundation.github.io/material-theme-builder/).
|
|
95
|
-
You can also find some references in ./dev/shared.css.
|
|
96
|
-
|
|
97
|
-
For the motion physics system, check [docs/05-Material_You_Expressive.md](./docs/05-Material_You_Expressive.md).
|
|
36
|
+
Check out [Overview](./docs/00-Overview.md).
|
|
98
37
|
|
|
99
38
|
## Documentations
|
|
100
39
|
|
|
101
|
-
[
|
|
40
|
+
- Previous [documentations and demos](https://tideover.cc/seele/docs/), being replaced
|
|
41
|
+
- [Documentations](./docs/00-Overview.md)
|
|
102
42
|
|
|
103
43
|
## Download
|
|
104
44
|
|
|
@@ -108,7 +48,7 @@ For the motion physics system, check [docs/05-Material_You_Expressive.md](./docs
|
|
|
108
48
|
|
|
109
49
|
## Browser Support
|
|
110
50
|
|
|
111
|
-
seele relies on the
|
|
51
|
+
seele relies on the following modern web standards:
|
|
112
52
|
|
|
113
53
|
- [`ElementInternals`](https://developer.mozilla.org/en-US/docs/Web/API/ElementInternals), Baseline 2023
|
|
114
54
|
- [Constructable Stylesheets](https://developer.mozilla.org/en-US/docs/Web/API/CSSStyleSheet/CSSStyleSheet), Baseline 2024, C[^1] 90, F 126
|
|
@@ -130,7 +70,7 @@ these following web features might be used and require higher browser versions:
|
|
|
130
70
|
|
|
131
71
|
## Other Information
|
|
132
72
|
|
|
133
|
-
- [Roadmap](./
|
|
73
|
+
- [Roadmap](./docs/01-Roadmap.md)
|
|
134
74
|
- [Contributing](./CONTRIBUTING.md)
|
|
135
75
|
- [License (Apache-2.0)](./LICENSE)
|
|
136
76
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vollowx/seele",
|
|
3
|
-
"version": "0.13.
|
|
3
|
+
"version": "0.13.2",
|
|
4
4
|
"description": "A extensible Web Components library, with Material Design 3 components pre-provided.",
|
|
5
5
|
"author": "vollowx",
|
|
6
6
|
"license": "Apache-2.0",
|
|
@@ -52,6 +52,7 @@
|
|
|
52
52
|
"@web/dev-server-esbuild": "^1.0.5",
|
|
53
53
|
"chokidar": "^5.0.0",
|
|
54
54
|
"lightningcss": "^1.33.0",
|
|
55
|
+
"minify-html-literals": "^1.3.5",
|
|
55
56
|
"prettier": "^3.9.6"
|
|
56
57
|
},
|
|
57
58
|
"dependencies": {
|
package/src/all.js
CHANGED
|
@@ -5,6 +5,8 @@ export { M3Button } from './m3/button/common-button.js';
|
|
|
5
5
|
export { M3ButtonToggle } from './m3/button/common-button-toggle.js';
|
|
6
6
|
export { M3IconButton } from './m3/button/icon-button.js';
|
|
7
7
|
export { M3IconButtonToggle } from './m3/button/icon-button-toggle.js';
|
|
8
|
+
export { M3StandardButtonGroup } from './m3/button-group/standard-button-group.js';
|
|
9
|
+
// export { M3ConnectedButtonGroup } from './m3/button-group/connected-button-group.js';
|
|
8
10
|
export { M3Checkbox } from './m3/checkbox/checkbox.js';
|
|
9
11
|
export { M3Dialog } from './m3/dialog/dialog.js';
|
|
10
12
|
export { M3Divider } from './m3/divider/divider.js';
|
package/src/base/autocomplete.js
CHANGED
|
@@ -11,10 +11,7 @@ const Base = FocusDelegated(InternalsAttached(LitElement));
|
|
|
11
11
|
return this.inputSlotElements[0];
|
|
12
12
|
}
|
|
13
13
|
render() {
|
|
14
|
-
return html
|
|
15
|
-
<slot name="input" @slotchange=${this.handleInputSlotChange}></slot>
|
|
16
|
-
${this.renderMenu()}
|
|
17
|
-
`;
|
|
14
|
+
return html`<slot name="input" @slotchange="${this.handleInputSlotChange}"></slot>${this.renderMenu()}`;
|
|
18
15
|
}
|
|
19
16
|
/**
|
|
20
17
|
* Example content:
|
package/src/base/input.js
CHANGED
|
@@ -16,47 +16,9 @@ export class Input extends Base {
|
|
|
16
16
|
const minLength = this.minLength > -1 ? this.minLength : nothing;
|
|
17
17
|
const maxLength = this.maxLength > -1 ? this.maxLength : nothing;
|
|
18
18
|
if (isTextarea) {
|
|
19
|
-
return html
|
|
20
|
-
<textarea
|
|
21
|
-
part="input"
|
|
22
|
-
.value=${live(this.value)}
|
|
23
|
-
placeholder=${this.placeholder || nothing}
|
|
24
|
-
?required=${this.required}
|
|
25
|
-
?readonly=${this.readOnly}
|
|
26
|
-
?disabled=${this.disabled}
|
|
27
|
-
minlength=${minLength}
|
|
28
|
-
maxlength=${maxLength}
|
|
29
|
-
autocomplete=${this.autocomplete || nothing}
|
|
30
|
-
@input=${this.handleInput}
|
|
31
|
-
@change=${this.handleChange}
|
|
32
|
-
@focus=${this.handleFocus}
|
|
33
|
-
@blur=${this.handleBlur}
|
|
34
|
-
></textarea>
|
|
35
|
-
`;
|
|
19
|
+
return html`<textarea part="input" .value="${live(this.value)}" placeholder="${this.placeholder || nothing}" ?required="${this.required}" ?readonly="${this.readOnly}" ?disabled="${this.disabled}" minlength="${minLength}" maxlength="${maxLength}" autocomplete="${this.autocomplete || nothing}" @input="${this.handleInput}" @change="${this.handleChange}" @focus="${this.handleFocus}" @blur="${this.handleBlur}"></textarea>`;
|
|
36
20
|
}
|
|
37
|
-
return html
|
|
38
|
-
<input
|
|
39
|
-
part="input"
|
|
40
|
-
type=${this.type}
|
|
41
|
-
.value=${live(this.value)}
|
|
42
|
-
placeholder=${this.placeholder || nothing}
|
|
43
|
-
?required=${this.required}
|
|
44
|
-
?readonly=${this.readOnly}
|
|
45
|
-
?disabled=${this.disabled}
|
|
46
|
-
?multiple=${this.multiple}
|
|
47
|
-
min=${this.min || nothing}
|
|
48
|
-
max=${this.max || nothing}
|
|
49
|
-
step=${this.step || nothing}
|
|
50
|
-
minlength=${minLength}
|
|
51
|
-
maxlength=${maxLength}
|
|
52
|
-
pattern=${this.pattern || nothing}
|
|
53
|
-
autocomplete=${this.autocomplete || nothing}
|
|
54
|
-
@input=${this.handleInput}
|
|
55
|
-
@change=${this.handleChange}
|
|
56
|
-
@focus=${this.handleFocus}
|
|
57
|
-
@blur=${this.handleBlur}
|
|
58
|
-
/>
|
|
59
|
-
`;
|
|
21
|
+
return html`<input part="input" type="${this.type}" .value="${live(this.value)}" placeholder="${this.placeholder || nothing}" ?required="${this.required}" ?readonly="${this.readOnly}" ?disabled="${this.disabled}" ?multiple="${this.multiple}" min="${this.min || nothing}" max="${this.max || nothing}" step="${this.step || nothing}" minlength="${minLength}" maxlength="${maxLength}" pattern="${this.pattern || nothing}" autocomplete="${this.autocomplete || nothing}" @input="${this.handleInput}" @change="${this.handleChange}" @focus="${this.handleFocus}" @blur="${this.handleBlur}">`;
|
|
60
22
|
}
|
|
61
23
|
updated(changedProperties) {
|
|
62
24
|
super.updated(changedProperties);
|
package/src/base/list.js
CHANGED
|
@@ -17,7 +17,7 @@ const Base = InternalsAttached(LitElement);
|
|
|
17
17
|
return this.listController.items || [];
|
|
18
18
|
}
|
|
19
19
|
render() {
|
|
20
|
-
return html
|
|
20
|
+
return html`${this.renderItemSlot()}`;
|
|
21
21
|
}
|
|
22
22
|
renderItemSlot() {
|
|
23
23
|
return html`<slot part="items"></slot>`;
|
package/src/base/menu.js
CHANGED
|
@@ -21,15 +21,7 @@ const Base = FocusDelegated(InternalsAttached(Attachable(LitElement)));
|
|
|
21
21
|
return this.listController.items || [];
|
|
22
22
|
}
|
|
23
23
|
render() {
|
|
24
|
-
return html`<div
|
|
25
|
-
part="menu"
|
|
26
|
-
role="${this.type}"
|
|
27
|
-
tabindex="${this.tabIndex}"
|
|
28
|
-
@keydown=${this.#handleKeyDown.bind(this)}
|
|
29
|
-
@focusout=${this.#handleFocusOut.bind(this)}
|
|
30
|
-
>
|
|
31
|
-
${this.renderItemSlot()}
|
|
32
|
-
</div>`;
|
|
24
|
+
return html`<div part="menu" role="${this.type}" tabindex="${this.tabIndex}" @keydown="${this.#handleKeyDown.bind(this)}" @focusout="${this.#handleFocusOut.bind(this)}">${this.renderItemSlot()}</div>`;
|
|
33
25
|
}
|
|
34
26
|
renderItemSlot() {
|
|
35
27
|
return html`<slot part="items"></slot>`;
|
package/src/base/select.js
CHANGED
|
@@ -94,7 +94,7 @@ const Base = FormAssociated(FocusDelegated(InternalsAttached(LitElement)));
|
|
|
94
94
|
return html``;
|
|
95
95
|
}
|
|
96
96
|
renderFieldContent() {
|
|
97
|
-
return html`<span part="value">${this.displayText || html
|
|
97
|
+
return html`<span part="value">${this.displayText || html` `}</span>`;
|
|
98
98
|
}
|
|
99
99
|
constructor(){
|
|
100
100
|
super(), // Form-related
|
package/src/base/slider.js
CHANGED
|
@@ -43,31 +43,10 @@ export class Slider extends Base {
|
|
|
43
43
|
}
|
|
44
44
|
renderInput({ start, value, ariaLabel, ariaValueText, ariaMin, ariaMax }) {
|
|
45
45
|
const name = start ? `start` : `end`;
|
|
46
|
-
return html`<input
|
|
47
|
-
type="range"
|
|
48
|
-
class="${classMap({
|
|
46
|
+
return html`<input type="range" class="${classMap({
|
|
49
47
|
start,
|
|
50
48
|
end: !start
|
|
51
|
-
})}"
|
|
52
|
-
@focus=${this.handleFocus}
|
|
53
|
-
@pointerdown=${this.handleDown}
|
|
54
|
-
@pointerup=${this.handleUp}
|
|
55
|
-
@keydown=${this.handleKeydown}
|
|
56
|
-
@keyup=${this.handleKeyup}
|
|
57
|
-
@input=${this.handleInput}
|
|
58
|
-
@change=${this.handleChange}
|
|
59
|
-
id=${name}
|
|
60
|
-
.disabled=${this.disabled}
|
|
61
|
-
.min=${String(this.min)}
|
|
62
|
-
aria-valuemin=${ariaMin}
|
|
63
|
-
.max=${String(this.max)}
|
|
64
|
-
aria-valuemax=${ariaMax}
|
|
65
|
-
.step=${String(this.step)}
|
|
66
|
-
.value=${String(value)}
|
|
67
|
-
.tabIndex=${start ? 1 : 0}
|
|
68
|
-
aria-label=${ariaLabel || nothing}
|
|
69
|
-
aria-valuetext=${ariaValueText}
|
|
70
|
-
/>`;
|
|
49
|
+
})}" @focus="${this.handleFocus}" @pointerdown="${this.handleDown}" @pointerup="${this.handleUp}" @keydown="${this.handleKeydown}" @keyup="${this.handleKeyup}" @input="${this.handleInput}" @change="${this.handleChange}" id="${name}" .disabled="${this.disabled}" .min="${String(this.min)}" aria-valuemin="${ariaMin}" .max="${String(this.max)}" aria-valuemax="${ariaMax}" .step="${String(this.step)}" .value="${String(value)}" .tabIndex="${start ? 1 : 0}" aria-label="${ariaLabel || nothing}" aria-valuetext="${ariaValueText}">`;
|
|
71
50
|
}
|
|
72
51
|
constructor(){
|
|
73
52
|
super(), this.min = 0, this.max = 100, this.valueLabel = '', this.valueLabelStart = '', this.valueLabelEnd = '', this.ariaLabelStart = '', this.ariaValueTextStart = '', this.ariaLabelEnd = '', this.ariaValueTextEnd = '', this.step = 1, this.ticks = false, this.labeled = false, this.range = false, this.startOnTop = false, this.handlesOverlapping = false, this.isRedispatchingEvent = false, // @TODO: Delegate ARIA attributes to inputs, automatically convert from
|
package/src/base/tabs.js
CHANGED
|
@@ -12,11 +12,7 @@ import { internals } from './mixins/internals-attached.js';
|
|
|
12
12
|
return this.parentNode instanceof ShadowRoot ? this.parentNode.host : this.parentElement;
|
|
13
13
|
}
|
|
14
14
|
render() {
|
|
15
|
-
return html
|
|
16
|
-
<div part="tablist" role="tablist">
|
|
17
|
-
<slot @slotchange=${this.#handleSlotChange}></slot>
|
|
18
|
-
</div>
|
|
19
|
-
`;
|
|
15
|
+
return html`<div part="tablist" role="tablist"><slot @slotchange="${this.#handleSlotChange}"></slot></div>`;
|
|
20
16
|
}
|
|
21
17
|
connectedCallback() {
|
|
22
18
|
super.connectedCallback();
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
import { css } from 'lit';
|
|
2
|
-
export const autocompleteStyles = css`:host{-webkit-user-select:none;user-select:none;min-width:210px;display:inline-block;position:relative}::slotted([slot=input]){cursor:pointer;outline:
|
|
2
|
+
export const autocompleteStyles = css`:host{-webkit-user-select:none;user-select:none;min-width:210px;display:inline-block;position:relative}::slotted([slot=input]){cursor:pointer;outline:0;width:100%}[part=menu]{--md-menu-max-height:300px;min-width:100%}`;
|
|
@@ -10,26 +10,7 @@ export class M3Autocomplete extends Autocomplete {
|
|
|
10
10
|
];
|
|
11
11
|
}
|
|
12
12
|
renderMenu() {
|
|
13
|
-
return html
|
|
14
|
-
<md-menu
|
|
15
|
-
part="menu"
|
|
16
|
-
id="menu"
|
|
17
|
-
type="listbox"
|
|
18
|
-
data-tabindex="-1"
|
|
19
|
-
?quick="${this.quick}"
|
|
20
|
-
.offset=${this.offset}
|
|
21
|
-
.align=${this.align}
|
|
22
|
-
.alignStrategy=${this.alignStrategy}
|
|
23
|
-
?keep-open-select=${this.keepOpenSelect}
|
|
24
|
-
no-focus-control
|
|
25
|
-
?open=${this.open}
|
|
26
|
-
@open="${()=>this.open = true}"
|
|
27
|
-
@close="${()=>this.open = false}"
|
|
28
|
-
@select=${this.handleMenuSelect}
|
|
29
|
-
>
|
|
30
|
-
<slot @slotchange=${this.handleItemsSlotChange}></slot>
|
|
31
|
-
</md-menu>
|
|
32
|
-
`;
|
|
13
|
+
return html`<md-menu part="menu" id="menu" type="listbox" data-tabindex="-1" ?quick="${this.quick}" .offset="${this.offset}" .align="${this.align}" .alignStrategy="${this.alignStrategy}" ?keep-open-select="${this.keepOpenSelect}" no-focus-control ?open="${this.open}" @open="${()=>this.open = true}" @close="${()=>this.open = false}" @select="${this.handleMenuSelect}"><slot @slotchange="${this.handleItemsSlotChange}"></slot></md-menu>`;
|
|
33
14
|
}
|
|
34
15
|
}
|
|
35
16
|
M3Autocomplete = _ts_decorate([
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
import { css } from 'lit';
|
|
2
|
-
export const badgeStyles = css`:host{--md-badge-offset:0}[part~=root]{vertical-align:middle;flex-shrink:0;display:inline-flex;position:relative}[part~=badge]{--md-badge-scale:1;top:var(--md-badge-offset);right:var(--md-badge-offset);box-sizing:border-box;font:var(--md-sys-typography-label-small);z-index:1;background-color:var(--md-sys-color-error);min-width:16px;height:16px;color:var(--md-sys-color-on-error);transform:scale(var(--md-badge-scale)) translate(50
|
|
2
|
+
export const badgeStyles = css`:host{--md-badge-offset:0}[part~=root]{vertical-align:middle;flex-shrink:0;display:inline-flex;position:relative}[part~=badge]{--md-badge-scale:1;top:var(--md-badge-offset);right:var(--md-badge-offset);box-sizing:border-box;font:var(--md-sys-typography-label-small);z-index:1;background-color:var(--md-sys-color-error);min-width:16px;height:16px;color:var(--md-sys-color-on-error);transform:scale(var(--md-badge-scale)) translate(50%,-50%);transform-origin:100% 0;transition:transform var(--md-sys-motion-spatial-fast-duration) var(--md-sys-motion-spatial-fast),color var(--md-sys-motion-effects-fast-duration) var(--md-sys-motion-effects-fast);pointer-events:none;border-radius:8px;flex-flow:wrap;justify-content:center;align-items:center;padding:0 2.5px;display:flex;position:absolute}:host([small]) [part~=badge]{--md-badge-scale:.375;color:#0000}:host([hidden]){display:hidden}:host([hidden]) [part~=badge],:host([value="0"]:not([show-zero])) [part~=badge]{--md-badge-scale:0}:host([circle]){--md-badge-offset:14%}:host(:not([left])[dir=rtl]) [part~=badge],:host([left]:not([dir=rtl])) [part~=badge]{right:auto;left:var(--md-badge-offset);transform:scale(var(--md-badge-scale)) translate(-50%,-50%);transform-origin:0 0}:host([bottom]) [part~=badge]{top:auto;bottom:var(--md-badge-offset);transform:scale(var(--md-badge-scale)) translate(50%,50%);transform-origin:100% 100%}:host(:not([left])[dir=rtl][bottom]) [part~=badge],:host([left][bottom]:not([dir=rtl])) [part~=badge]{transform:scale(var(--md-badge-scale)) translate(-50%,50%);transform-origin:0 100%}`;
|
package/src/m3/badge/badge.js
CHANGED
|
@@ -9,12 +9,7 @@ export class M3Badge extends LitElement {
|
|
|
9
9
|
];
|
|
10
10
|
}
|
|
11
11
|
render() {
|
|
12
|
-
return html
|
|
13
|
-
<div part="root">
|
|
14
|
-
<slot></slot>
|
|
15
|
-
<span part="badge">${this.#getDisplayValue()}</span>
|
|
16
|
-
</div>
|
|
17
|
-
`;
|
|
12
|
+
return html`<div part="root"><slot></slot><span part="badge">${this.#getDisplayValue()}</span></div>`;
|
|
18
13
|
}
|
|
19
14
|
#getDisplayValue() {
|
|
20
15
|
const value = this.value;
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
import { css } from 'lit';
|
|
2
|
-
export const commonButtonStyles = css`@layer common-button{
|
|
2
|
+
export const commonButtonStyles = css`@layer common-button{block-size:1em;font-size:var(--_icon-size);inline-size:1em}`;
|
|
@@ -19,15 +19,7 @@ export class M3ButtonToggle extends ToggleButton {
|
|
|
19
19
|
];
|
|
20
20
|
}
|
|
21
21
|
render() {
|
|
22
|
-
return html
|
|
23
|
-
<md-focus-ring></md-focus-ring>
|
|
24
|
-
<md-ripple></md-ripple>
|
|
25
|
-
<span part="target"></span>
|
|
26
|
-
<slot part="icon unchecked" name="icon" aria-hidden="true"></slot>
|
|
27
|
-
<slot part="icon checked" name="icon-checked" aria-hidden="true"></slot>
|
|
28
|
-
<slot part="label unchecked"></slot>
|
|
29
|
-
<slot part="label checked" name="checked"></slot>
|
|
30
|
-
`;
|
|
22
|
+
return html`<md-focus-ring></md-focus-ring><md-ripple></md-ripple><span part="target"></span><slot part="icon unchecked" name="icon" aria-hidden="true"></slot><slot part="icon checked" name="icon-checked" aria-hidden="true"></slot><slot part="label unchecked"></slot><slot part="label checked" name="checked"></slot>`;
|
|
31
23
|
}
|
|
32
24
|
constructor(...args){
|
|
33
25
|
super(...args), this.size = 'small', this.shape = 'rounded', this.color = 'primary', this.variant = 'filled', /**
|
|
@@ -17,13 +17,7 @@ export class M3Button extends Button {
|
|
|
17
17
|
];
|
|
18
18
|
}
|
|
19
19
|
render() {
|
|
20
|
-
return html
|
|
21
|
-
<md-focus-ring></md-focus-ring>
|
|
22
|
-
<md-ripple></md-ripple>
|
|
23
|
-
<span part="target"></span>
|
|
24
|
-
<slot part="icon" name="icon" aria-hidden="true"></slot>
|
|
25
|
-
<slot part="label"></slot>
|
|
26
|
-
`;
|
|
20
|
+
return html`<md-focus-ring></md-focus-ring><md-ripple></md-ripple><span part="target"></span><slot part="icon" name="icon" aria-hidden="true"></slot><slot part="label"></slot>`;
|
|
27
21
|
}
|
|
28
22
|
constructor(...args){
|
|
29
23
|
super(...args), this.size = 'small', this.shape = 'rounded', this.color = 'primary', this.variant = 'filled', /**
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
import { css } from 'lit';
|
|
2
|
-
export const iconButtonStyles = css
|
|
2
|
+
export const iconButtonStyles = css``;
|
|
@@ -19,13 +19,7 @@ export class M3IconButtonToggle extends ToggleButton {
|
|
|
19
19
|
];
|
|
20
20
|
}
|
|
21
21
|
render() {
|
|
22
|
-
return html
|
|
23
|
-
<md-focus-ring></md-focus-ring>
|
|
24
|
-
<md-ripple enterbehavior="always"></md-ripple>
|
|
25
|
-
<span part="target"></span>
|
|
26
|
-
<slot part="icon unchecked"></slot>
|
|
27
|
-
<slot part="icon checked" name="checked"></slot>
|
|
28
|
-
`;
|
|
22
|
+
return html`<md-focus-ring></md-focus-ring><md-ripple enterbehavior="always"></md-ripple><span part="target"></span><slot part="icon unchecked"></slot><slot part="icon checked" name="checked"></slot>`;
|
|
29
23
|
}
|
|
30
24
|
constructor(...args){
|
|
31
25
|
super(...args), this.size = 'small', this.color = 'primary', this.variant = 'text', this.width = 'standard';
|
|
@@ -17,12 +17,7 @@ export class M3IconButton extends Button {
|
|
|
17
17
|
];
|
|
18
18
|
}
|
|
19
19
|
render() {
|
|
20
|
-
return html
|
|
21
|
-
<md-focus-ring></md-focus-ring>
|
|
22
|
-
<md-ripple></md-ripple>
|
|
23
|
-
<span part="target"></span>
|
|
24
|
-
<slot part="icon"></slot>
|
|
25
|
-
`;
|
|
20
|
+
return html`<md-focus-ring></md-focus-ring><md-ripple></md-ripple><span part="target"></span><slot part="icon"></slot>`;
|
|
26
21
|
}
|
|
27
22
|
constructor(...args){
|
|
28
23
|
super(...args), this.size = 'small', this.color = 'primary', this.variant = 'text', this.width = 'standard';
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
import { css } from 'lit';
|
|
2
|
-
export const sharedButtonStyles = css
|
|
2
|
+
export const sharedButtonStyles = css``;
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
import { css } from 'lit';
|
|
2
|
-
export const sharedButtonToggleStyles = css
|
|
2
|
+
export const sharedButtonToggleStyles = css``;
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
import { _ as _ts_decorate } from "@swc/helpers/_/_ts_decorate";
|
|
2
|
+
import { LitElement, html } from 'lit';
|
|
3
|
+
import { customElement } from '../../core/decorators.js';
|
|
4
|
+
import { queryAssignedElements } from 'lit/decorators.js';
|
|
5
|
+
import { standardButtonGroupStyles } from './standard-button-group-styles.css.js';
|
|
6
|
+
const EXPAND_FACTOR = 1.15;
|
|
7
|
+
const shapeAnimation = Symbol('shapeAnimation');
|
|
8
|
+
export class M3StandardButtonGroup extends LitElement {
|
|
9
|
+
static{
|
|
10
|
+
this.styles = [
|
|
11
|
+
standardButtonGroupStyles
|
|
12
|
+
];
|
|
13
|
+
}
|
|
14
|
+
render() {
|
|
15
|
+
return html`<slot @slotchange="${this.#handleSlotChange}"></slot>`;
|
|
16
|
+
}
|
|
17
|
+
connectedCallback() {
|
|
18
|
+
super.connectedCallback();
|
|
19
|
+
this.addEventListener('pointerdown', this.#handlePointerDown);
|
|
20
|
+
this.addEventListener('keydown', this.#handleKeyDown, {
|
|
21
|
+
capture: true
|
|
22
|
+
});
|
|
23
|
+
window.addEventListener('pointerup', this.#reset);
|
|
24
|
+
window.addEventListener('pointercancel', this.#reset);
|
|
25
|
+
window.addEventListener('keyup', this.#reset, {
|
|
26
|
+
capture: true
|
|
27
|
+
});
|
|
28
|
+
this.#resizeObserver = new ResizeObserver((entries)=>{
|
|
29
|
+
if (this.#activeIndex !== -1) return; // Skip if animating
|
|
30
|
+
entries.forEach((entry)=>{
|
|
31
|
+
const target = entry.target;
|
|
32
|
+
const index = this.$buttons.indexOf(target);
|
|
33
|
+
if (index !== -1) {
|
|
34
|
+
const currentWidth = target.style.width;
|
|
35
|
+
target.style.width = '';
|
|
36
|
+
this.#baseWidths[index] = entry.target.getBoundingClientRect().width;
|
|
37
|
+
if (currentWidth) target.style.width = currentWidth;
|
|
38
|
+
}
|
|
39
|
+
});
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
disconnectedCallback() {
|
|
43
|
+
window.removeEventListener('pointerup', this.#reset);
|
|
44
|
+
window.removeEventListener('pointercancel', this.#reset);
|
|
45
|
+
window.removeEventListener('keyup', this.#reset, {
|
|
46
|
+
capture: true
|
|
47
|
+
});
|
|
48
|
+
this.#resizeObserver.disconnect();
|
|
49
|
+
super.disconnectedCallback();
|
|
50
|
+
}
|
|
51
|
+
#activeIndex;
|
|
52
|
+
#resizeObserver;
|
|
53
|
+
#baseWidths;
|
|
54
|
+
#handleSlotChange;
|
|
55
|
+
#handlePointerDown;
|
|
56
|
+
#handleKeyDown;
|
|
57
|
+
#reset;
|
|
58
|
+
/**
|
|
59
|
+
* Passing no element resets all shape changes
|
|
60
|
+
*/ updateLayout(target = null) {
|
|
61
|
+
const pressedIndex = target ? this.$buttons.indexOf(target) : -1;
|
|
62
|
+
this.#activeIndex = pressedIndex;
|
|
63
|
+
const pressedBaseWidth = pressedIndex !== -1 ? this.#baseWidths[pressedIndex] : 0;
|
|
64
|
+
const expansionDelta = pressedBaseWidth * (EXPAND_FACTOR - 1);
|
|
65
|
+
const isPressedAtEdge = pressedIndex === 0 || pressedIndex === this.$buttons.length - 1;
|
|
66
|
+
this.$buttons.forEach((btn, i)=>{
|
|
67
|
+
const currentWidth = btn.getBoundingClientRect().width;
|
|
68
|
+
let targetWidth = this.#baseWidths[i];
|
|
69
|
+
if (pressedIndex !== -1) {
|
|
70
|
+
if (i === pressedIndex) {
|
|
71
|
+
targetWidth = pressedBaseWidth * EXPAND_FACTOR;
|
|
72
|
+
} else if (Math.abs(i - pressedIndex) === 1) {
|
|
73
|
+
if (isPressedAtEdge) targetWidth = this.#baseWidths[i] - expansionDelta;
|
|
74
|
+
else targetWidth = this.#baseWidths[i] - expansionDelta / 2;
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
const styles = getComputedStyle(this);
|
|
78
|
+
const rawDuration = styles.getPropertyValue('--md-sys-motion-spatial-fast-duration');
|
|
79
|
+
const rawEasing = styles.getPropertyValue('--md-sys-motion-spatial-fast');
|
|
80
|
+
const duration = parseInt(rawDuration.substring(0, rawDuration.length - 2)) || 0;
|
|
81
|
+
const easing = rawEasing || 'ease';
|
|
82
|
+
if (btn[shapeAnimation]) btn[shapeAnimation].cancel();
|
|
83
|
+
btn[shapeAnimation] = btn.animate([
|
|
84
|
+
{
|
|
85
|
+
width: `${currentWidth}px`
|
|
86
|
+
},
|
|
87
|
+
{
|
|
88
|
+
width: `${targetWidth}px`
|
|
89
|
+
}
|
|
90
|
+
], {
|
|
91
|
+
duration,
|
|
92
|
+
easing,
|
|
93
|
+
fill: 'forwards'
|
|
94
|
+
});
|
|
95
|
+
btn[shapeAnimation].onfinish = ()=>{
|
|
96
|
+
if (pressedIndex === -1) {
|
|
97
|
+
btn.style.width = '';
|
|
98
|
+
btn[shapeAnimation].cancel();
|
|
99
|
+
}
|
|
100
|
+
};
|
|
101
|
+
});
|
|
102
|
+
}
|
|
103
|
+
constructor(...args){
|
|
104
|
+
super(...args), this.#activeIndex = -1, this.#baseWidths = [], this.#handleSlotChange = ()=>{
|
|
105
|
+
this.#resizeObserver.disconnect();
|
|
106
|
+
this.$buttons.forEach((btn, i)=>{
|
|
107
|
+
this.#baseWidths[i] = btn.getBoundingClientRect().width;
|
|
108
|
+
this.#resizeObserver.observe(btn);
|
|
109
|
+
});
|
|
110
|
+
}, this.#handlePointerDown = (e)=>{
|
|
111
|
+
if (this === e.target) return;
|
|
112
|
+
this.updateLayout(e.target);
|
|
113
|
+
}, this.#handleKeyDown = (e)=>{
|
|
114
|
+
if (e.key !== ' ' && e.key !== 'Enter') return;
|
|
115
|
+
this.updateLayout(e.target);
|
|
116
|
+
}, this.#reset = (e)=>{
|
|
117
|
+
if (e && e.type === 'keyup' && e.key !== ' ' && e.key !== 'Enter') return;
|
|
118
|
+
if (this.#activeIndex !== -1) {
|
|
119
|
+
this.#activeIndex = -1;
|
|
120
|
+
this.updateLayout();
|
|
121
|
+
}
|
|
122
|
+
};
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
_ts_decorate([
|
|
126
|
+
queryAssignedElements()
|
|
127
|
+
], M3StandardButtonGroup.prototype, "$buttons", void 0);
|
|
128
|
+
M3StandardButtonGroup = _ts_decorate([
|
|
129
|
+
customElement('md-button-group', false)
|
|
130
|
+
], M3StandardButtonGroup);
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
import { css } from 'lit';
|
|
2
|
-
export const checkboxStyles = css`:host{--md-focus-ring-radius:9999px;--_container-color:transparent;--_outline-color:var(--md-sys-color-on-surface-variant);--_mark-color:var(--md-sys-color-surface-container-highest);--_ripple-color:var(--md-sys-color-on-surface);--_checkbox-size:18px;background-color:color-mix(in srgb,
|
|
2
|
+
export const checkboxStyles = css`:host{--md-focus-ring-radius:9999px;--_container-color:transparent;--_outline-color:var(--md-sys-color-on-surface-variant);--_mark-color:var(--md-sys-color-surface-container-highest);--_ripple-color:var(--md-sys-color-on-surface);--_checkbox-size:18px;background-color:color-mix(in srgb,var(--_container-color) var(--_container-opacity,100%),transparent);border-color:color-mix(in srgb,var(--_outline-color) var(--_outline-opacity,100%),transparent);border-style:solid;border-width:var(--md-checkbox-outline-width,2px);box-sizing:border-box;cursor:pointer;height:var(--_checkbox-size);-webkit-tap-highlight-color:transparent;transition:background-color var(--md-sys-motion-effects-fast-duration) var(--md-sys-motion-effects-fast),border-color var(--md-sys-motion-effects-fast-duration) var(--md-sys-motion-effects-fast);-webkit-user-select:none;user-select:none;vertical-align:top;width:var(--_checkbox-size);border-radius:2px;outline:0;place-content:center;place-items:center;margin:15px;display:inline-grid;position:relative}:host(:state(checked)),:host(:state(indeterminate)){--_container-color:var(--md-sys-color-primary);--_outline-color:var(--md-sys-color-primary);--_mark-color:var(--md-sys-color-on-primary);--_mark-opacity:100%;--_ripple-color:var(--md-sys-color-primary)}:host([error]){--_outline-color:var(--md-sys-color-error);--_mark-color:var(--md-sys-color-surface-container-highest);--_ripple-color:var(--md-sys-color-error)}:host([error]:state(checked)),:host([error]:state(indeterminate)){--_container-color:var(--md-sys-color-error);--_outline-color:var(--md-sys-color-error);--_mark-color:var(--md-sys-color-on-error);--_ripple-color:var(--md-sys-color-error)}:host(:disabled){--_outline-color:var(--md-sys-color-on-surface);--_outline-opacity:38%;--_mark-color:var(--md-sys-color-surface-container-highest);cursor:default;pointer-events:none}:host(:disabled:state(checked)),:host(:disabled:state(indeterminate)){--_container-color:var(--md-sys-color-on-surface);--_container-opacity:38%;--_outline-color:var(--md-sys-color-surface);--_outline-opacity:0%;--_mark-color:var(--md-sys-color-surface)}@media (hover:hover) and (pointer:fine){:host(:hover){--_unchecked-outline-color:var(--md-sys-color-on-surface)}}@media (forced-colors:active){:host{forced-color-adjust:none}}:host(:disabled){--_unchecked-container-opacity:38%}[part~=icon]{fill:color-mix(in srgb,var(--_mark-color) var(--_mark-opacity,0),transparent);height:18px;transition:fill var(--md-sys-motion-effects-fast-duration) var(--md-sys-motion-effects-fast);width:18px;position:absolute;inset:-2px}[part~=mark]{transition-duration:var(--md-sys-motion-effects-default-duration);transition-timing-function:var(--md-sys-motion-effects-default);transform:scaleY(-1) translate(7px,-14px) rotate(45deg)}:host(:state(indeterminate)) [part~=mark]{transform:scaleY(-1) translate(4px,-10px) rotate(0)}:host(:state(checked)) [part~=mark],:host(:state(indeterminate)) [part~=mark]{transition-duration:var(--md-sys-motion-effects-default-duration);transition-timing-function:var(--md-sys-motion-effects-default)}[part~=mark-short]{width:2px;height:0;transition-property:transform,height}[part~=mark-long]{width:0;height:2px;transition-property:transform,width}:host(:not(:state(checked)):not(:state(indeterminate)):state(was-checked)) [part~=mark],:host(:not(:state(checked)):not(:state(indeterminate)):state(was-indeterminate)) [part~=mark]{transition-delay:var(--md-sys-motion-effects-fast-duration)}:host(:state(checked)) [part~=mark-short]{height:5.65685px}:host(:state(checked)) [part~=mark-long]{width:11.3137px}:host(:state(checked):state(was-unchecked)) [part~=mark-short]{transition-property:none}:host(:state(indeterminate)) [part~=mark-short]{height:2px}:host(:state(indeterminate)) [part~=mark-long]{width:10px}:host(:state(indeterminate):state(was-unchecked)) [part~=mark-short]{transition-property:height}:host(:state(indeterminate):state(was-unchecked)) [part~=mark-long]{transition-property:width}md-focus-ring{height:44px;inset:unset;width:44px}md-ripple{--md-ripple-color:var(--_ripple-color);height:40px;inset:unset;border-radius:9999px;width:40px}`;
|
|
@@ -14,20 +14,10 @@ export class M3Checkbox extends Checkbox {
|
|
|
14
14
|
];
|
|
15
15
|
}
|
|
16
16
|
render() {
|
|
17
|
-
return html
|
|
18
|
-
<md-focus-ring></md-focus-ring>
|
|
19
|
-
<md-ripple enterbehavior="none"></md-ripple>
|
|
20
|
-
<span part="target"></span>
|
|
21
|
-
${this.renderIcon()}
|
|
22
|
-
`;
|
|
17
|
+
return html`<md-focus-ring></md-focus-ring><md-ripple enterbehavior="none"></md-ripple><span part="target"></span> ${this.renderIcon()}`;
|
|
23
18
|
}
|
|
24
19
|
renderIcon() {
|
|
25
|
-
return html
|
|
26
|
-
<svg part="icon" viewBox="0 0 18 18" aria-hidden="true">
|
|
27
|
-
<rect part="mark mark-short"></rect>
|
|
28
|
-
<rect part="mark mark-long"></rect>
|
|
29
|
-
</svg>
|
|
30
|
-
`;
|
|
20
|
+
return html`<svg part="icon" viewBox="0 0 18 18" aria-hidden="true"><rect part="mark mark-short"></rect><rect part="mark mark-long"></rect></svg>`;
|
|
31
21
|
}
|
|
32
22
|
constructor(...args){
|
|
33
23
|
super(...args), this.error = false;
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
import { css } from 'lit';
|
|
2
|
-
export const dialogStyles = css`dialog{background:0 0;border:none;outline:0;min-width:280px;max-width:min(560px,100% - 48px);min-height:140px;max-height:min(560px,100% - 48px);padding:0;overflow:visible}dialog[open]{display:flex}dialog::backdrop{background:0 0}[part=container]{box-sizing:border-box;will-change:height,
|
|
2
|
+
export const dialogStyles = css`dialog{background:0 0;border:none;outline:0;min-width:280px;max-width:min(560px,100% - 48px);min-height:140px;max-height:min(560px,100% - 48px);padding:0;overflow:visible}dialog[open]{display:flex}dialog::backdrop{background:0 0}[part=container]{box-sizing:border-box;will-change:height,transform,opacity;background-color:var(--md-sys-color-surface-container-high);border-radius:28px;flex-direction:column;flex-grow:1;padding-top:8px;display:flex;position:relative;overflow:hidden}[part=headline]{flex-direction:column;display:flex}::slotted([slot=icon]){block-size:1em;color:var(--md-sys-color-secondary);fill:currentColor;inline-size:1em;margin:16px 0 0;font-size:24px}::slotted([slot=headline]){box-sizing:border-box;font:var(--md-sys-typography-headline-small);color:var(--md-sys-color-on-surface);margin:0;padding:16px 24px 0}[part=headline].has-icon{align-items:center}[part=content]{color:var(--md-sys-color-on-surface-variant);font:var(--md-sys-typography-body-medium);will-change:opacity;padding:16px 24px 0;display:block}[part=actions]{justify-content:flex-end;gap:8px;display:flex;position:absolute;bottom:0;left:0;right:0}slot[name=actions]::slotted(*){box-sizing:border-box;justify-content:flex-end;gap:8px;padding:24px;display:flex}[part=scrim]{background:var(--md-sys-color-scrim);opacity:.32;pointer-events:none;z-index:1;display:none;position:fixed;inset:0}dialog[open]+[part=scrim]{display:block}`;
|