@expressivecss/expressive 0.7.0-rc.0 → 0.8.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/CHANGELOG.md +1311 -1
- package/README.md +14 -11
- package/dist/css/expressive.css +4215 -1668
- package/dist/css/expressive.css.map +1 -1
- package/dist/css/expressive.min.css +1 -1
- package/dist/css/expressive.min.css.map +1 -1
- package/dist/js/expressive.cjs +1231 -1253
- package/dist/js/expressive.cjs.map +4 -4
- package/dist/js/expressive.js +1231 -1253
- package/dist/js/expressive.js.map +4 -4
- package/dist/js/expressive.min.js +12 -12
- package/dist/js/expressive.min.js.map +4 -4
- package/dist/js/expressive.mjs +1231 -1253
- package/dist/js/expressive.mjs.map +4 -4
- package/dist/types/behaviors/bottomSheets.d.ts +19 -11
- package/dist/types/behaviors/sheetDrag.d.ts +40 -0
- package/dist/types/behaviors/sideSheets.d.ts +2 -9
- package/dist/types/components/autocomplete.d.ts +15 -3
- package/dist/types/components/buttons.d.ts +5 -1
- package/dist/types/components/carousel.d.ts +87 -53
- package/dist/types/components/chips.d.ts +21 -1
- package/dist/types/components/expandingCard.d.ts +31 -0
- package/dist/types/components/index.d.ts +21 -20
- package/dist/types/components/lightbox.d.ts +1 -0
- package/dist/types/components/menu.d.ts +7 -1
- package/dist/types/components/{sidenav.d.ts → navigationDrawer.d.ts} +16 -16
- package/dist/types/components/registry.d.ts +8 -8
- package/dist/types/components/slider.d.ts +26 -85
- package/dist/types/components/snackbar.d.ts +20 -5
- package/dist/types/components/tabs.d.ts +12 -0
- package/dist/types/components/timepicker.d.ts +12 -9
- package/dist/types/core/utils.d.ts +64 -53
- package/dist/types/index.d.ts +8 -9
- package/package.json +15 -1
- package/src/sass/README.md +61 -11
- package/src/sass/abstracts/_breakpoints.scss +17 -19
- package/src/sass/abstracts/_mixins.scss +103 -21
- package/src/sass/abstracts/_variables.scss +50 -5
- package/src/sass/base/_global.scss +6 -24
- package/src/sass/base/_grid.scss +15 -12
- package/src/sass/base/_normalize.scss +34 -38
- package/src/sass/base/_typography.scss +4 -18
- package/src/sass/components/_badges.scss +2 -3
- package/src/sass/components/_banners.scss +298 -0
- package/src/sass/components/_bottom-app-bar.scss +180 -0
- package/src/sass/components/_bottom-sheet.scss +12 -4
- package/src/sass/components/_button-groups.scss +186 -0
- package/src/sass/components/_buttons.scss +245 -92
- package/src/sass/components/_cards.scss +494 -73
- package/src/sass/components/_carousel.scss +562 -68
- package/src/sass/components/_chips.scss +64 -5
- package/src/sass/components/_datepicker.scss +24 -24
- package/src/sass/components/_dialog.scss +17 -11
- package/src/sass/components/_drag-handle.scss +130 -0
- package/src/sass/components/_expanding-card.scss +260 -0
- package/src/sass/components/_fab-menu.scss +232 -0
- package/src/sass/components/_floating-sheet.scss +86 -0
- package/src/sass/components/_icon-buttons.scss +194 -0
- package/src/sass/components/_icons-material-design.scss +16 -4
- package/src/sass/components/_index.scss +22 -6
- package/src/sass/components/_list.scss +16 -13
- package/src/sass/components/_loading-indicator.scss +106 -0
- package/src/sass/components/_menu.scss +335 -61
- package/src/sass/components/_navbar.scss +71 -24
- package/src/sass/components/_navigation-bar.scss +13 -10
- package/src/sass/components/{_sidenav.scss → _navigation-drawer.scss} +123 -33
- package/src/sass/components/_navigation-rail.scss +22 -22
- package/src/sass/components/_page-footer.scss +19 -16
- package/src/sass/components/_pagination.scss +24 -6
- package/src/sass/components/_panes.scss +52 -11
- package/src/sass/components/{_preloader.scss → _progress.scss} +11 -3
- package/src/sass/components/_scrim.scss +37 -0
- package/src/sass/components/_search.scss +259 -0
- package/src/sass/components/_segmented-buttons.scss +188 -0
- package/src/sass/components/_side-sheet.scss +2 -2
- package/src/sass/components/_snackbar.scss +20 -15
- package/src/sass/components/_split-button.scss +196 -0
- package/src/sass/components/_tabs.scss +7 -8
- package/src/sass/components/_timepicker.scss +67 -58
- package/src/sass/components/_toolbar.scss +206 -80
- package/src/sass/components/forms/_checkboxes.scss +49 -12
- package/src/sass/components/forms/_fieldset.scss +4 -4
- package/src/sass/components/forms/_file-input.scss +8 -1
- package/src/sass/components/forms/_index.scss +1 -1
- package/src/sass/components/forms/_input-fields.scss +50 -44
- package/src/sass/components/forms/_radio-buttons.scss +42 -10
- package/src/sass/components/forms/_select.scss +0 -1
- package/src/sass/components/forms/{_range.scss → _slider.scss} +8 -9
- package/src/sass/components/forms/_switches.scss +6 -7
- package/src/sass/tokens/_index.scss +4 -1
- package/src/sass/tokens/_reference.scss +70 -61
- package/src/sass/tokens/_state.scss +24 -0
- package/src/sass/tokens/_theme.scss +6 -3
- package/src/sass/tokens/_vibrant.scss +76 -0
- package/src/sass/utilities/_colors.scss +14 -1
- package/src/sass/utilities/_helpers.scss +5 -5
- package/src/sass/utilities/_visibility.scss +48 -26
- package/dist/types/behaviors/waves.d.ts +0 -15
- package/dist/types/components/parallax.d.ts +0 -16
- package/dist/types/components/range.d.ts +0 -43
- package/dist/types/core/bounding.d.ts +0 -6
- package/dist/types/core/edges.d.ts +0 -6
- package/src/sass/components/_parallax.scss +0 -104
- package/src/sass/components/_pulse.scss +0 -37
- package/src/sass/components/_slider.scss +0 -129
|
@@ -1,102 +1,43 @@
|
|
|
1
1
|
import { Component, BaseOptions, InitElements, InitElement } from '../core/component';
|
|
2
2
|
export interface SliderOptions extends BaseOptions {
|
|
3
|
-
/**
|
|
4
|
-
* Set to false to hide slide indicators.
|
|
5
|
-
* @default true
|
|
6
|
-
*/
|
|
7
|
-
indicators: boolean;
|
|
8
|
-
/**
|
|
9
|
-
* Set height of slider.
|
|
10
|
-
* @default 400
|
|
11
|
-
*/
|
|
12
|
-
height: number;
|
|
13
|
-
/**
|
|
14
|
-
* Set the duration of the transition animation in ms.
|
|
15
|
-
* @default 500
|
|
16
|
-
*/
|
|
17
|
-
duration: number;
|
|
18
|
-
/**
|
|
19
|
-
* Set the duration between transitions in ms.
|
|
20
|
-
* @default 6000
|
|
21
|
-
*/
|
|
22
|
-
interval: number;
|
|
23
|
-
/**
|
|
24
|
-
* If slider should pause when keyboard focus is received.
|
|
25
|
-
* @default true
|
|
26
|
-
*/
|
|
27
|
-
pauseOnFocus: boolean;
|
|
28
|
-
/**
|
|
29
|
-
* If slider should pause when is hovered by a pointer.
|
|
30
|
-
* @default true
|
|
31
|
-
*/
|
|
32
|
-
pauseOnHover: boolean;
|
|
33
|
-
/**
|
|
34
|
-
* Optional function used to generate ARIA label to indicators (for accessibility purposes).
|
|
35
|
-
* @param index Current index, starting from "1".
|
|
36
|
-
* @param current A which indicates whether it is the current element or not
|
|
37
|
-
* @returns a string to be used as label indicator.
|
|
38
|
-
* @default null
|
|
39
|
-
*/
|
|
40
|
-
indicatorLabelFunc: (index: number, current: boolean) => string;
|
|
41
3
|
}
|
|
42
4
|
export declare class Slider extends Component<SliderOptions> {
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
_slides: HTMLLIElement[];
|
|
49
|
-
_activeSlide: HTMLLIElement;
|
|
50
|
-
_indicators: HTMLLIElement[];
|
|
51
|
-
_hovered: boolean;
|
|
52
|
-
_focused: boolean;
|
|
53
|
-
_focusCurrent: boolean;
|
|
54
|
-
_sliderId: string;
|
|
55
|
-
constructor(el: HTMLElement, options: Partial<SliderOptions>);
|
|
5
|
+
el: HTMLInputElement;
|
|
6
|
+
private _pointerDown;
|
|
7
|
+
value: HTMLElement;
|
|
8
|
+
thumb: HTMLElement;
|
|
9
|
+
constructor(el: HTMLInputElement, options: Partial<SliderOptions>);
|
|
56
10
|
static get defaults(): SliderOptions;
|
|
57
11
|
/**
|
|
58
12
|
* Initializes instance of Slider.
|
|
59
13
|
* @param el HTML element.
|
|
60
14
|
* @param options Component options.
|
|
61
15
|
*/
|
|
62
|
-
static init(el:
|
|
16
|
+
static init(el: HTMLInputElement, options?: Partial<SliderOptions>): Slider;
|
|
63
17
|
/**
|
|
64
18
|
* Initializes instances of Slider.
|
|
65
19
|
* @param els HTML elements.
|
|
66
20
|
* @param options Component options.
|
|
67
21
|
*/
|
|
68
|
-
static init(els: InitElements<InitElement>, options?: Partial<SliderOptions>): Slider[];
|
|
69
|
-
static getInstance(el:
|
|
22
|
+
static init(els: InitElements<HTMLInputElement | InitElement>, options?: Partial<SliderOptions>): Slider[];
|
|
23
|
+
static getInstance(el: HTMLInputElement): Slider;
|
|
70
24
|
destroy(): void;
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
pause: () => void;
|
|
90
|
-
/**
|
|
91
|
-
* Start slider autoslide.
|
|
92
|
-
*/
|
|
93
|
-
start: () => void;
|
|
94
|
-
/**
|
|
95
|
-
* Move to next slider.
|
|
96
|
-
*/
|
|
97
|
-
next: () => void;
|
|
98
|
-
/**
|
|
99
|
-
* Move to prev slider.
|
|
100
|
-
*/
|
|
101
|
-
prev: () => void;
|
|
25
|
+
_setupEventHandlers(): void;
|
|
26
|
+
_removeEventHandlers(): void;
|
|
27
|
+
_handleRangeChange: () => void;
|
|
28
|
+
_handleRangePointerDown: (e: PointerEvent) => void;
|
|
29
|
+
_handleRangeInputOrMove: () => void;
|
|
30
|
+
_handleRangePointerUp: (e: PointerEvent) => void;
|
|
31
|
+
_handleRangeRelease: () => void;
|
|
32
|
+
_setupThumb(): void;
|
|
33
|
+
_removeThumb(): void;
|
|
34
|
+
_isVertical(): boolean;
|
|
35
|
+
_host(): HTMLElement | null;
|
|
36
|
+
_clampDual(): void;
|
|
37
|
+
_fraction(el: HTMLInputElement): number;
|
|
38
|
+
_sync(): void;
|
|
39
|
+
/**
|
|
40
|
+
* Initializes every range input in the current document.
|
|
41
|
+
*/
|
|
42
|
+
static Init(): void;
|
|
102
43
|
}
|
|
@@ -58,6 +58,14 @@ export interface SnackbarOptions extends BaseOptions {
|
|
|
58
58
|
* @default 0.8
|
|
59
59
|
*/
|
|
60
60
|
activationPercent: number;
|
|
61
|
+
/**
|
|
62
|
+
* Any element in the tree the snackbar should render into. A Snackbar has no
|
|
63
|
+
* originating element to infer this from, so pass one when the page lives in
|
|
64
|
+
* a shadow root — the container is appended to that root instead of to
|
|
65
|
+
* `document.body`, where a root-scoped stylesheet could not reach it.
|
|
66
|
+
* @default null
|
|
67
|
+
*/
|
|
68
|
+
root: HTMLElement;
|
|
61
69
|
}
|
|
62
70
|
export declare class Snackbar {
|
|
63
71
|
/** The snackbar element. */
|
|
@@ -86,15 +94,22 @@ export declare class Snackbar {
|
|
|
86
94
|
static _snackbars: Snackbar[];
|
|
87
95
|
static _container: HTMLElement;
|
|
88
96
|
static _draggedSnackbar: Snackbar;
|
|
97
|
+
/** Which pointer owns the drag in flight; a second finger is ignored. */
|
|
98
|
+
static _dragPointerId: number | null;
|
|
89
99
|
constructor(options?: Partial<SnackbarOptions>);
|
|
90
100
|
static get defaults(): SnackbarOptions;
|
|
91
101
|
static getInstance(el: HTMLElement): Snackbar;
|
|
92
|
-
static _createContainer(): void;
|
|
102
|
+
static _createContainer(root?: HTMLElement | ShadowRoot): void;
|
|
93
103
|
static _removeContainer(): void;
|
|
94
|
-
static _onDragStart(e:
|
|
95
|
-
static _onDragMove(e:
|
|
96
|
-
static _onDragEnd(): void;
|
|
97
|
-
|
|
104
|
+
static _onDragStart(e: PointerEvent): void;
|
|
105
|
+
static _onDragMove(e: PointerEvent): void;
|
|
106
|
+
static _onDragEnd(e: PointerEvent): void;
|
|
107
|
+
/**
|
|
108
|
+
* A cancelled pointer is not a short swipe. Snap back and resume the timer
|
|
109
|
+
* without consulting the distance travelled - the browser took the gesture
|
|
110
|
+
* over, so the movement so far says nothing about what the user wanted.
|
|
111
|
+
*/
|
|
112
|
+
static _onDragCancel(e: PointerEvent): void;
|
|
98
113
|
/**
|
|
99
114
|
* dismiss all snackbars.
|
|
100
115
|
*/
|
|
@@ -59,6 +59,18 @@ export declare class Tabs extends Component<TabsOptions> {
|
|
|
59
59
|
_queryTabLinks(): NodeListOf<HTMLAnchorElement>;
|
|
60
60
|
_handleTabClick: (e: MouseEvent) => void;
|
|
61
61
|
_createIndicator(): void;
|
|
62
|
+
/**
|
|
63
|
+
* Which tab is current, for the eye and for assistive technology.
|
|
64
|
+
*
|
|
65
|
+
* The class alone is a colour. `aria-current` is the part a screen reader
|
|
66
|
+
* reads, and because tabs are navigation rather than a tablist (rule 2 -
|
|
67
|
+
* there is no keyboard model here to back a tablist), "current" is exactly
|
|
68
|
+
* the right word for it. Its *value* changes as the user clicks, which makes
|
|
69
|
+
* maintaining it the component's job, not the author's - see CONTEXT.md on
|
|
70
|
+
* static semantics versus dynamic state. Writing it once in the markup and
|
|
71
|
+
* never moving it left the old tab announcing itself as current.
|
|
72
|
+
*/
|
|
73
|
+
private _setActiveTabLink;
|
|
62
74
|
_setupActiveTabLink(): void;
|
|
63
75
|
_setupSwipeableTabs(): void;
|
|
64
76
|
_teardownSwipeableTabs(): void;
|
|
@@ -95,10 +95,6 @@ export interface TimepickerOptions extends BaseOptions {
|
|
|
95
95
|
*/
|
|
96
96
|
displayPluginOptions: object;
|
|
97
97
|
}
|
|
98
|
-
type Point = {
|
|
99
|
-
x: number;
|
|
100
|
-
y: number;
|
|
101
|
-
};
|
|
102
98
|
export declare class Timepicker extends Component<TimepickerOptions> {
|
|
103
99
|
el: HTMLInputElement;
|
|
104
100
|
id: string;
|
|
@@ -110,6 +106,8 @@ export declare class Timepicker extends Component<TimepickerOptions> {
|
|
|
110
106
|
x0: number;
|
|
111
107
|
y0: number;
|
|
112
108
|
moved: boolean;
|
|
109
|
+
/** Which pointer is dragging the clock hand; a second finger is ignored. */
|
|
110
|
+
private _dragPointerId;
|
|
113
111
|
dx: number;
|
|
114
112
|
dy: number;
|
|
115
113
|
/**
|
|
@@ -161,7 +159,6 @@ export declare class Timepicker extends Component<TimepickerOptions> {
|
|
|
161
159
|
static init(els: InitElements<HTMLInputElement | InitElement>, options?: Partial<TimepickerOptions>): Timepicker[];
|
|
162
160
|
static _addLeadingZero(num: number): string;
|
|
163
161
|
static _createSVGEl(name: string): SVGElement;
|
|
164
|
-
static _Pos(e: TouchEvent | MouseEvent): Point;
|
|
165
162
|
static getInstance(el: HTMLElement): Timepicker;
|
|
166
163
|
destroy(): void;
|
|
167
164
|
_setupEventHandlers(): void;
|
|
@@ -169,9 +166,16 @@ export declare class Timepicker extends Component<TimepickerOptions> {
|
|
|
169
166
|
_handleInputClick: () => void;
|
|
170
167
|
_handleInputKeydown: (e: KeyboardEvent) => void;
|
|
171
168
|
_handleTimeInputEnterKey: (e: KeyboardEvent) => void;
|
|
172
|
-
_handleClockClickStart: (e:
|
|
173
|
-
_handleDocumentClickMove: (e:
|
|
174
|
-
_handleDocumentClickEnd: (e:
|
|
169
|
+
_handleClockClickStart: (e: PointerEvent) => void;
|
|
170
|
+
_handleDocumentClickMove: (e: PointerEvent) => void;
|
|
171
|
+
_handleDocumentClickEnd: (e: PointerEvent) => void;
|
|
172
|
+
/**
|
|
173
|
+
* A cancelled pointer is not a completed selection. The browser or the OS
|
|
174
|
+
* took the gesture over, so this only lets go of the drag - it must not run
|
|
175
|
+
* the pointer-up path, which advances hours to minutes, fires `onSelect`,
|
|
176
|
+
* and under `autoSubmit` closes the picker on a time the user never chose.
|
|
177
|
+
*/
|
|
178
|
+
_handleDocumentClickCancel: (e: PointerEvent) => void;
|
|
175
179
|
_insertHTMLIntoDOM(): void;
|
|
176
180
|
_setupVariables(): void;
|
|
177
181
|
_pickerSetup(): void;
|
|
@@ -210,4 +214,3 @@ export declare class Timepicker extends Component<TimepickerOptions> {
|
|
|
210
214
|
cancel: () => void;
|
|
211
215
|
clear: () => void;
|
|
212
216
|
}
|
|
213
|
-
export {};
|
|
@@ -1,55 +1,32 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
/** The part of a `DOMRect` the positioning helpers below actually read. */
|
|
2
|
+
type Bounding = Pick<DOMRect, 'left' | 'top' | 'width' | 'height'>;
|
|
3
|
+
/** Which edges of a container a box has crossed. */
|
|
4
|
+
type Edges = {
|
|
5
|
+
top: boolean;
|
|
6
|
+
right: boolean;
|
|
7
|
+
bottom: boolean;
|
|
8
|
+
left: boolean;
|
|
9
|
+
};
|
|
3
10
|
/**
|
|
4
11
|
* Class with utilitary functions for global usage.
|
|
5
12
|
*/
|
|
6
13
|
export declare class Utils {
|
|
7
|
-
/** Specifies wether tab is pressed or not. */
|
|
8
|
-
static tabPressed: boolean;
|
|
9
|
-
/** Specifies wether there is a key pressed. */
|
|
10
|
-
static keyDown: boolean;
|
|
11
14
|
/**
|
|
12
|
-
* Key maps.
|
|
15
|
+
* Key maps. One `KeyboardEvent.key` value each: the second entries these used
|
|
16
|
+
* to carry (`Esc`, `Up`, `Del`, ...) were IE and Edge Legacy spellings, and
|
|
17
|
+
* the support baseline excludes both.
|
|
13
18
|
*/
|
|
14
19
|
static keys: {
|
|
15
|
-
TAB: string
|
|
16
|
-
ENTER: string
|
|
17
|
-
ESC: string
|
|
18
|
-
BACKSPACE: string
|
|
19
|
-
ARROW_UP: string
|
|
20
|
-
ARROW_DOWN: string
|
|
21
|
-
ARROW_LEFT: string
|
|
22
|
-
ARROW_RIGHT: string
|
|
23
|
-
DELETE: string
|
|
20
|
+
TAB: string;
|
|
21
|
+
ENTER: string;
|
|
22
|
+
ESC: string;
|
|
23
|
+
BACKSPACE: string;
|
|
24
|
+
ARROW_UP: string;
|
|
25
|
+
ARROW_DOWN: string;
|
|
26
|
+
ARROW_LEFT: string;
|
|
27
|
+
ARROW_RIGHT: string;
|
|
28
|
+
DELETE: string;
|
|
24
29
|
};
|
|
25
|
-
/**
|
|
26
|
-
* Keys that count as keyboard navigation, precomputed.
|
|
27
|
-
*
|
|
28
|
-
* These handlers run at capture phase on the document for every keystroke on
|
|
29
|
-
* the page, and used to rebuild three arrays and spread them into a fourth
|
|
30
|
-
* on each one.
|
|
31
|
-
*/
|
|
32
|
-
private static _navigationKeys;
|
|
33
|
-
/**
|
|
34
|
-
* Detects when a key is pressed.
|
|
35
|
-
* @param e Event instance.
|
|
36
|
-
*/
|
|
37
|
-
static docHandleKeydown(e: KeyboardEvent): void;
|
|
38
|
-
/**
|
|
39
|
-
* Detects when a key is released.
|
|
40
|
-
* @param e Event instance.
|
|
41
|
-
*/
|
|
42
|
-
static docHandleKeyup(e: KeyboardEvent): void;
|
|
43
|
-
/**
|
|
44
|
-
* Detects when document is focused.
|
|
45
|
-
* @param e Event instance.
|
|
46
|
-
*/
|
|
47
|
-
static docHandleFocus(e: FocusEvent): void;
|
|
48
|
-
/**
|
|
49
|
-
* Detects when document is not focused.
|
|
50
|
-
* @param e Event instance.
|
|
51
|
-
*/
|
|
52
|
-
static docHandleBlur(e: FocusEvent): void;
|
|
53
30
|
/**
|
|
54
31
|
* Run `callback` once the document is parsed.
|
|
55
32
|
*
|
|
@@ -60,9 +37,39 @@ export declare class Utils {
|
|
|
60
37
|
*/
|
|
61
38
|
static onDocumentReady(callback: () => void): void;
|
|
62
39
|
/**
|
|
63
|
-
* Generates a unique string identifier.
|
|
40
|
+
* Generates a unique string identifier. Every caller prefixes the result and
|
|
41
|
+
* uses it as an element id, and a UUID is valid in that position.
|
|
42
|
+
*
|
|
43
|
+
* `randomUUID` is exposed only in secure contexts, and a dev server on a
|
|
44
|
+
* plain-HTTP LAN address - the usual way a page is opened on a phone - is
|
|
45
|
+
* not one. Without the fallback every component that stamps an id would
|
|
46
|
+
* throw there. The ids only have to be unique within one document, so the
|
|
47
|
+
* fallback does not need to be cryptographic.
|
|
64
48
|
*/
|
|
65
49
|
static guid(): string;
|
|
50
|
+
/**
|
|
51
|
+
* Where an element created at runtime has to be appended to stay in the same
|
|
52
|
+
* tree as `el`. A stylesheet adopted into a shadow root cannot match a node
|
|
53
|
+
* in the document, so a portal that lands on `document.body` is unstyled
|
|
54
|
+
* whenever its origin lives in a shadow root (adr/0002).
|
|
55
|
+
*
|
|
56
|
+
* Light-DOM elements still get `document.body`, which is what escapes an
|
|
57
|
+
* ancestor's `overflow: hidden` and stacking context. Inside a shadow root
|
|
58
|
+
* both hazards come back: the host's own ancestors still form the containing
|
|
59
|
+
* block, so a transformed ancestor re-anchors `position: fixed` and a
|
|
60
|
+
* positioned one re-anchors `position: absolute`.
|
|
61
|
+
*/
|
|
62
|
+
static portalRoot(el: Node): HTMLElement | ShadowRoot;
|
|
63
|
+
/**
|
|
64
|
+
* `getElementById` against the tree `el` lives in. The mirror of
|
|
65
|
+
* `portalRoot`: an id in a shadow root is invisible to
|
|
66
|
+
* `document.getElementById`, so a trigger and its target inside the same
|
|
67
|
+
* root could not find each other at all.
|
|
68
|
+
*
|
|
69
|
+
* Falls back to the document for a detached `el`, whose root is a plain
|
|
70
|
+
* element with no lookup of its own.
|
|
71
|
+
*/
|
|
72
|
+
static getElementById(el: Node, id: string): HTMLElement;
|
|
66
73
|
/**
|
|
67
74
|
* Checks for exceeded edges
|
|
68
75
|
* @param container Container element.
|
|
@@ -101,15 +108,18 @@ export declare class Utils {
|
|
|
101
108
|
*/
|
|
102
109
|
static getDocumentScrollLeft(): number;
|
|
103
110
|
/**
|
|
104
|
-
*
|
|
105
|
-
*
|
|
106
|
-
*
|
|
107
|
-
*
|
|
111
|
+
* Trailing-edge throttle: run `func` now, then at most once per `wait` ms
|
|
112
|
+
* with the most recent arguments.
|
|
113
|
+
*
|
|
114
|
+
* This used to carry its underscore ancestor's whole configuration - leading
|
|
115
|
+
* and trailing switches, a result passthrough - and both call sites are
|
|
116
|
+
* resize handlers passing nothing but a function and a delay.
|
|
117
|
+
*
|
|
118
|
+
* Assign the return value once. `x = Utils.throttle(fn, 200)` is right;
|
|
119
|
+
* wrapping it in an arrow builds a fresh closure per event and never calls
|
|
120
|
+
* it, which is how resize handling was dead in three components.
|
|
108
121
|
*/
|
|
109
|
-
static throttle(func: (...args: unknown[]) => void, wait: number
|
|
110
|
-
leading: boolean;
|
|
111
|
-
trailing: boolean;
|
|
112
|
-
}>): (...args: unknown[]) => any;
|
|
122
|
+
static throttle(func: (...args: unknown[]) => void, wait: number): (...args: unknown[]) => void;
|
|
113
123
|
/**
|
|
114
124
|
* Renders confirm/close buttons with callback function
|
|
115
125
|
*/
|
|
@@ -127,3 +137,4 @@ export declare class Utils {
|
|
|
127
137
|
y: number;
|
|
128
138
|
};
|
|
129
139
|
}
|
|
140
|
+
export {};
|
package/dist/types/index.d.ts
CHANGED
|
@@ -1,9 +1,8 @@
|
|
|
1
|
-
export * from
|
|
2
|
-
export { Dialogs } from
|
|
3
|
-
export { BottomSheets } from
|
|
4
|
-
export { SideSheets } from
|
|
5
|
-
export { Forms } from
|
|
6
|
-
export {
|
|
7
|
-
export {
|
|
8
|
-
export
|
|
9
|
-
export declare const version = "0.7.0-rc.0";
|
|
1
|
+
export * from "./components";
|
|
2
|
+
export { Dialogs } from "./behaviors/dialogs";
|
|
3
|
+
export { BottomSheets } from "./behaviors/bottomSheets";
|
|
4
|
+
export { SideSheets } from "./behaviors/sideSheets";
|
|
5
|
+
export { Forms } from "./behaviors/forms";
|
|
6
|
+
export { AutoInit } from "./components/registry";
|
|
7
|
+
export type { AutoInitOptions } from "./components/registry";
|
|
8
|
+
export declare const version = "0.8.0";
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@expressivecss/expressive",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.8.0",
|
|
4
4
|
"description": "ExpressiveCSS - a Material Design 3 front-end framework.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "BaezFJ <baezdevs@gmail.com>",
|
|
@@ -69,10 +69,20 @@
|
|
|
69
69
|
"build:js:iife": "esbuild src/ts/index.ts --bundle --format=iife --global-name=Expressive --target=es2020 --outfile=dist/js/expressive.js --sourcemap",
|
|
70
70
|
"build:js:iife-min": "esbuild src/ts/index.ts --bundle --format=iife --global-name=Expressive --target=es2020 --outfile=dist/js/expressive.min.js --minify --sourcemap",
|
|
71
71
|
"build:types": "tsc -p tsconfig.build.json",
|
|
72
|
+
"build:semantics": "node scripts/gen-semantics.mjs",
|
|
73
|
+
"docs:dev": "run-s build docs:watch",
|
|
74
|
+
"docs:watch": "run-p watch:css watch:js docs:server",
|
|
75
|
+
"docs:server": "astro dev --root docs",
|
|
76
|
+
"docs:build": "run-s build docs:build:astro docs:verify",
|
|
77
|
+
"docs:build:astro": "astro build --root docs",
|
|
78
|
+
"docs:preview": "astro preview --root docs",
|
|
79
|
+
"docs:verify": "node scripts/verify-site.mjs",
|
|
72
80
|
"typecheck": "tsc -p tsconfig.json --noEmit",
|
|
73
81
|
"test": "run-s build:js build:css test:run",
|
|
74
82
|
"test:run": "node --test",
|
|
75
83
|
"test:watch": "node --test --watch",
|
|
84
|
+
"test:visual": "node visual/run.mjs",
|
|
85
|
+
"test:visual:report": "playwright show-report visual/report",
|
|
76
86
|
"watch": "run-p watch:css watch:js",
|
|
77
87
|
"watch:css": "sass --watch src/sass/expressive.scss:dist/css/expressive.css --style=expanded --source-map --load-path=src/sass",
|
|
78
88
|
"watch:js": "esbuild src/ts/index.ts --bundle --format=iife --global-name=Expressive --target=es2020 --outfile=dist/js/expressive.js --sourcemap --watch=forever"
|
|
@@ -87,10 +97,14 @@
|
|
|
87
97
|
"not dead"
|
|
88
98
|
],
|
|
89
99
|
"devDependencies": {
|
|
100
|
+
"@playwright/test": "^1.56.0",
|
|
101
|
+
"astro": "^7.2.8",
|
|
90
102
|
"esbuild": "^0.28.2",
|
|
91
103
|
"jsdom": "^30.0.1",
|
|
92
104
|
"npm-run-all2": "^9.0.3",
|
|
93
105
|
"sass": "^1.102.0",
|
|
106
|
+
"turndown": "^7.2.4",
|
|
107
|
+
"turndown-plugin-gfm": "^1.0.2",
|
|
94
108
|
"typescript": "^7.0.2"
|
|
95
109
|
}
|
|
96
110
|
}
|
package/src/sass/README.md
CHANGED
|
@@ -65,21 +65,26 @@ fine — it crosses no boundary.
|
|
|
65
65
|
|
|
66
66
|
## Breakpoints
|
|
67
67
|
|
|
68
|
-
|
|
68
|
+
The five Material 3 window size classes live in
|
|
69
|
+
`abstracts/_breakpoints.scss` and are reached through mixins:
|
|
69
70
|
|
|
70
71
|
```scss
|
|
71
|
-
@include bp-up("
|
|
72
|
-
@include bp-down("
|
|
73
|
-
@include bp-between("
|
|
72
|
+
@include bp-up("medium") { } // width >= 600px
|
|
73
|
+
@include bp-down("expanded") { } // width < 840px
|
|
74
|
+
@include bp-between("expanded", "large") { } // 840px–1199px
|
|
74
75
|
```
|
|
75
76
|
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
77
|
+
| M3 class | Width | Grid prefix |
|
|
78
|
+
| --- | --- | --- |
|
|
79
|
+
| Compact | `< 600px` | `.s` (default) |
|
|
80
|
+
| Medium | `600–839px` | `.m` |
|
|
81
|
+
| Expanded | `840–1199px` | `.l` |
|
|
82
|
+
| Large | `1200–1599px` | `.xl` |
|
|
83
|
+
| Extra-large | `>= 1600px` | `.xxl` |
|
|
84
|
+
|
|
85
|
+
The grid prefixes remain unchanged for markup compatibility. At Extra-large,
|
|
86
|
+
`.container` lifts its 1280px cap to 1920px. Range syntax uses exclusive
|
|
87
|
+
comparators, so each boundary is written once without fractional max-widths.
|
|
83
88
|
|
|
84
89
|
## Theming
|
|
85
90
|
|
|
@@ -126,6 +131,51 @@ only has to set `color-scheme: dark` and all 30 tokens re-resolve — and settin
|
|
|
126
131
|
`color-scheme` on any subtree re-themes just that subtree. `color-scheme` is
|
|
127
132
|
load-bearing now; changing it is not cosmetic.
|
|
128
133
|
|
|
134
|
+
## Shadow roots
|
|
135
|
+
|
|
136
|
+
The sheet is supported as a shadow root's **only** stylesheet — adopted into
|
|
137
|
+
`shadowRoot.adoptedStyleSheets` with no copy in the document. So a rule that
|
|
138
|
+
declares a token pairs its anchor with the `:host` twin that reaches the same
|
|
139
|
+
elements from inside a shadow tree:
|
|
140
|
+
|
|
141
|
+
```scss
|
|
142
|
+
// no - :root matches the document element and nothing else, so this token
|
|
143
|
+
// is simply absent in a shadow-only load, and every declaration reading it
|
|
144
|
+
// is then invalid at computed-value time
|
|
145
|
+
:root { --md-comp-nav-drawer-width: 300px; }
|
|
146
|
+
|
|
147
|
+
// yes
|
|
148
|
+
:root, :host { --md-comp-nav-drawer-width: 300px; }
|
|
149
|
+
:root[theme='dark'], :host([theme='dark']) { color-scheme: dark; }
|
|
150
|
+
[vibrant], :host([vibrant]) { … }
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
An anchor is anything that can only match a document root or a descendant of
|
|
154
|
+
one, which is `html` and `body` as well: a shadow root has neither inside it.
|
|
155
|
+
`base/_grid.scss` put `--gap-size` on `body` and `.row` reads it without a
|
|
156
|
+
fallback, so a `.row` in a shadow-only load had an invalid `gap` rather than a
|
|
157
|
+
default one.
|
|
158
|
+
|
|
159
|
+
`color-scheme` counts as a token here: `light-dark()` resolves against the
|
|
160
|
+
element's used `color-scheme`, so an unpaired `:root[theme='dark']` means a
|
|
161
|
+
shadow tree cannot be pinned to a theme the way a page can.
|
|
162
|
+
|
|
163
|
+
`:host` matches nothing in a document, so pairing an anchor cannot change a
|
|
164
|
+
normal load. It is not weightless, though: bare `:host` matches `:root` at
|
|
165
|
+
(0,1,0), but `:host(<compound>)` adds its argument's weight on top, so
|
|
166
|
+
`:host([vibrant])` is (0,2,0) against `[vibrant]`'s (0,1,0). The two arms match
|
|
167
|
+
disjoint elements and never compete, so nothing in the sheet turns on it — but
|
|
168
|
+
do not reach for the pairing as a way to keep specificity flat.
|
|
169
|
+
|
|
170
|
+
`tests/shadow-dom.test.js` fails any rule that skips the pairing; the commitment
|
|
171
|
+
behind it is `adr/0002-shadow-only-stylesheet-adoption.md`. That commitment
|
|
172
|
+
covers everything *inside* the shadow root, portals included: the six places that
|
|
173
|
+
create an element at runtime (Tooltip, Snackbar, Lightbox's caption, the drawer's
|
|
174
|
+
drag target, and the Datepicker's two menus) route through `Utils.portalRoot()`
|
|
175
|
+
and append into the originating shadow root, so no document-level copy is needed.
|
|
176
|
+
The cost is that they no longer escape an ancestor's `overflow` or stacking
|
|
177
|
+
context — the ADR states what that re-anchors.
|
|
178
|
+
|
|
129
179
|
## Translucent colors
|
|
130
180
|
|
|
131
181
|
```scss
|
|
@@ -1,38 +1,36 @@
|
|
|
1
1
|
@use "sass:map";
|
|
2
2
|
@use "sass:list";
|
|
3
3
|
|
|
4
|
-
//
|
|
4
|
+
// Material 3 window size classes, expressed as media-query boundaries.
|
|
5
5
|
//
|
|
6
6
|
// The old form built a query by interpolating a whole string:
|
|
7
7
|
//
|
|
8
8
|
// $medium-and-down: "only screen and (max-width : 992.99px)";
|
|
9
9
|
// @media #{$medium-and-down} { ... }
|
|
10
10
|
//
|
|
11
|
-
// which needed the `.99` because
|
|
12
|
-
//
|
|
13
|
-
//
|
|
11
|
+
// which needed the `.99` because inclusive max/min queries both match on the
|
|
12
|
+
// boundary pixel. Range syntax has an exclusive comparator, so fractional
|
|
13
|
+
// values are unnecessary and every boundary is stated once:
|
|
14
14
|
//
|
|
15
|
-
// @include bp-down("
|
|
15
|
+
// @include bp-down("expanded") { ... } -> @media (width < 840px)
|
|
16
16
|
//
|
|
17
17
|
// `only screen` went with them: it existed to hide queries from Netscape 4
|
|
18
18
|
// and IE, and `screen` alone excludes print anyway - which these rules never
|
|
19
19
|
// wanted to do, since a hidden element should stay hidden on paper.
|
|
20
20
|
|
|
21
|
-
//
|
|
22
|
-
//
|
|
23
|
-
//
|
|
24
|
-
//
|
|
25
|
-
//
|
|
26
|
-
//
|
|
27
|
-
//
|
|
28
|
-
// expanded 840 ≤ width < 1200 "large" is 993, close enough
|
|
29
|
-
// large 1200 ≤ width < 1600 "xlarge"
|
|
30
|
-
// extra-large width ≥ 1600 "xxlarge"
|
|
21
|
+
// Compact starts at zero and is the unwrapped/default style. The remaining
|
|
22
|
+
// entries are the exact lower bounds from the M3 adaptive-layout spec:
|
|
23
|
+
// compact 0 ≤ width < 600
|
|
24
|
+
// medium 600 ≤ width < 840
|
|
25
|
+
// expanded 840 ≤ width < 1200
|
|
26
|
+
// large 1200 ≤ width < 1600
|
|
27
|
+
// extra-large width ≥ 1600
|
|
31
28
|
$breakpoints: (
|
|
32
|
-
"
|
|
33
|
-
"
|
|
34
|
-
"
|
|
35
|
-
"
|
|
29
|
+
"compact": 0px,
|
|
30
|
+
"medium": 600px,
|
|
31
|
+
"expanded": 840px,
|
|
32
|
+
"large": 1200px,
|
|
33
|
+
"extra-large": 1600px,
|
|
36
34
|
) !default;
|
|
37
35
|
|
|
38
36
|
@function breakpoint($name) {
|