@noxlovette/material 0.8.3 → 0.9.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/claude-skill/material-design/SKILL.md +1 -1
- package/claude-skill/material-design/references/component-patterns.md +36 -1
- package/dist/animation/presence.svelte.js +37 -1
- package/dist/animation/sharedAxisTransition.d.ts +2 -1
- package/dist/animation/sharedAxisTransition.js +19 -1
- package/dist/components/buttons/FAB.svelte +4 -1
- package/dist/components/buttons/theme.d.ts +6 -3
- package/dist/components/buttons/theme.js +3 -2
- package/dist/components/containers/context-menu/theme.js +4 -4
- package/dist/components/containers/list/theme.js +1 -1
- package/dist/components/containers/menu/Menu.svelte +2 -5
- package/dist/components/containers/menu/theme.js +4 -2
- package/dist/components/containers/pane/theme.js +1 -1
- package/dist/components/date/theme.js +1 -1
- package/dist/components/forms/command/Command.mdx +90 -0
- package/dist/components/forms/command/Command.stories.svelte +69 -10
- package/dist/components/forms/command/Command.stories.svelte.d.ts +2 -17
- package/dist/components/forms/command/CommandDialog.svelte +58 -0
- package/dist/components/forms/command/CommandDialog.svelte.d.ts +11 -0
- package/dist/components/forms/command/CommandItem.svelte +48 -5
- package/dist/components/forms/command/CommandItem.svelte.d.ts +4 -0
- package/dist/components/forms/command/index.d.ts +1 -0
- package/dist/components/forms/command/index.js +1 -0
- package/dist/components/forms/command/theme.d.ts +371 -6
- package/dist/components/forms/command/theme.js +32 -1
- package/dist/components/forms/command/types.d.ts +27 -1
- package/dist/components/forms/search/Search.mdx +9 -0
- package/dist/components/forms/search/Search.stories.svelte +14 -2
- package/dist/components/forms/search/Search.svelte +41 -9
- package/dist/components/forms/search/Search.svelte.d.ts +3 -0
- package/dist/components/forms/search/SearchView.svelte +57 -6
- package/dist/components/forms/search/SearchView.svelte.d.ts +4 -2
- package/dist/components/forms/search/theme.js +4 -2
- package/dist/components/forms/search/types.d.ts +14 -1
- package/dist/components/forms/slider/theme.js +1 -1
- package/dist/components/nav/appbar/AppBar.stories.svelte +30 -2
- package/dist/components/nav/appbar/AppBar.svelte +40 -8
- package/dist/components/nav/appbar/theme.js +1 -1
- package/dist/components/nav/appbar/types.d.ts +14 -0
- package/dist/components/nav/navbar/theme.js +1 -1
- package/dist/components/nav/rail/Rail.mdx +6 -0
- package/dist/components/nav/rail/Rail.svelte +55 -1
- package/dist/components/nav/rail/Rail.svelte.d.ts +3 -0
- package/dist/components/nav/rail/theme.js +1 -1
- package/dist/components/nav/rail/types.d.ts +7 -0
- package/dist/components/toolbar/theme.js +4 -1
- package/dist/styles/motion.css +26 -0
- package/dist/utils/Layer.svelte +3 -1
- package/dist/utils/index.d.ts +1 -0
- package/dist/utils/index.js +1 -0
- package/dist/utils/shortcut.d.ts +26 -0
- package/dist/utils/shortcut.js +84 -0
- package/package.json +1 -1
|
@@ -33,7 +33,10 @@ export const toolbar = tv({
|
|
|
33
33
|
},
|
|
34
34
|
variant: {
|
|
35
35
|
floating: { root: 'inline-flex', segment: 'rounded-full shadow-elevation-1' },
|
|
36
|
-
docked: {
|
|
36
|
+
docked: {
|
|
37
|
+
root: 'md-vt-persist fixed left-spacing-0 z-layer-bar w-full',
|
|
38
|
+
segment: 'w-full rounded-none'
|
|
39
|
+
}
|
|
37
40
|
},
|
|
38
41
|
color: {
|
|
39
42
|
standard: { segment: 'bg-md-sys-color-surface-container' },
|
package/dist/styles/motion.css
CHANGED
|
@@ -371,3 +371,29 @@
|
|
|
371
371
|
background-color: var(--md-container-transform-color, transparent);
|
|
372
372
|
box-shadow: var(--md-container-transform-shadow, none);
|
|
373
373
|
}
|
|
374
|
+
|
|
375
|
+
/*
|
|
376
|
+
App chrome stays put through navigation transitions (#50). Motion's `animateView` puts the
|
|
377
|
+
`target` region (or the root) in its own layer, and the whole `::view-transition` tree paints
|
|
378
|
+
over the live page, so a fixed bar outside `main` was covered by `main`'s snapshots and a fixed
|
|
379
|
+
toolbar or FAB inside it faded and scaled with the page. `md-vt-persist` lifts an element
|
|
380
|
+
into its own layer that is drawn above the page's and never animates: the old snapshot is
|
|
381
|
+
hidden and the new one is the live element.
|
|
382
|
+
|
|
383
|
+
Scoped to the navigation helpers (sharedAxis, lateral, fadeThrough), which set
|
|
384
|
+
`md-navigation-transition` on the root while they run, so a container transform (the search
|
|
385
|
+
view) still grows over the Navbar instead of under it. Built into Navbar, viewport-anchored
|
|
386
|
+
Rail, AppBar and docked Toolbar; add the class to an app-positioned floating Toolbar or FAB.
|
|
387
|
+
Browsers without `match-element` fall back to the old behaviour.
|
|
388
|
+
*/
|
|
389
|
+
:root.md-navigation-transition .md-vt-persist {
|
|
390
|
+
view-transition-name: match-element;
|
|
391
|
+
view-transition-class: md-persist;
|
|
392
|
+
}
|
|
393
|
+
::view-transition-group(*.md-persist),
|
|
394
|
+
::view-transition-new(*.md-persist) {
|
|
395
|
+
animation: none !important;
|
|
396
|
+
}
|
|
397
|
+
::view-transition-old(*.md-persist) {
|
|
398
|
+
display: none;
|
|
399
|
+
}
|
package/dist/utils/Layer.svelte
CHANGED
|
@@ -194,7 +194,9 @@
|
|
|
194
194
|
:global(input:disabled + .layer-container) > .tint,
|
|
195
195
|
:global(:disabled) > .tint
|
|
196
196
|
) {
|
|
197
|
-
|
|
197
|
+
/* pointer: fine too — some touch phones report hover: hover, and a
|
|
198
|
+
tapped element keeps :hover until the next tap elsewhere (#48). */
|
|
199
|
+
@media (hover: hover) and (pointer: fine) {
|
|
198
200
|
&:is(:global(:hover) > .tint, :global(:active) > .tint) {
|
|
199
201
|
opacity: 0.08;
|
|
200
202
|
}
|
package/dist/utils/index.d.ts
CHANGED
package/dist/utils/index.js
CHANGED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A keyboard shortcut, written as `aria-keyshortcuts` writes one: modifiers, then the key, joined
|
|
3
|
+
* by `+`. `'/'`, `'Mod+K'`, `'Alt+Shift+P'`. `Mod` is ⌘ on Apple platforms and Ctrl elsewhere,
|
|
4
|
+
* the key each platform's apps use for their own shortcuts.
|
|
5
|
+
*/
|
|
6
|
+
export type Shortcut = string;
|
|
7
|
+
/** Whether this is an Apple platform, where `Mod` is ⌘. False during SSR. */
|
|
8
|
+
export declare function isApplePlatform(): boolean;
|
|
9
|
+
/**
|
|
10
|
+
* Whether a keydown is this shortcut. Modifiers must match exactly. Digits match by physical key,
|
|
11
|
+
* since Alt+1 types `¡` on a Mac; letters match by the character typed, falling back to the
|
|
12
|
+
* physical key on non-Latin layouts, so ⌘K still works with a Cyrillic layout on.
|
|
13
|
+
*/
|
|
14
|
+
export declare function matchesShortcut(e: KeyboardEvent, shortcut: Shortcut, apple?: boolean): boolean;
|
|
15
|
+
/** Whether a keydown's target takes text, where a bare `/` is typing, not a shortcut. */
|
|
16
|
+
export declare function isEditableTarget(target: EventTarget | null): boolean;
|
|
17
|
+
/**
|
|
18
|
+
* Whether a page-wide shortcut should fire for this keydown: it matches, nothing handled the key
|
|
19
|
+
* first, no IME is composing, a shortcut without ⌘/Ctrl/Alt isn't being typed into a field, and
|
|
20
|
+
* no modal dialog other than the one holding `owner` is open.
|
|
21
|
+
*/
|
|
22
|
+
export declare function triggersShortcut(e: KeyboardEvent, shortcut: Shortcut | null | undefined, owner?: Element | null): boolean;
|
|
23
|
+
/** The shortcut for `aria-keyshortcuts`, with `Mod` resolved for this platform. */
|
|
24
|
+
export declare function ariaKeyShortcut(shortcut: Shortcut, apple?: boolean): string;
|
|
25
|
+
/** The shortcut as people read it on this platform: `⌘K` on a Mac, `Ctrl+K` elsewhere. */
|
|
26
|
+
export declare function shortcutLabel(shortcut: Shortcut, apple?: boolean): string;
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
/** Whether this is an Apple platform, where `Mod` is ⌘. False during SSR. */
|
|
2
|
+
export function isApplePlatform() {
|
|
3
|
+
if (typeof navigator === 'undefined')
|
|
4
|
+
return false;
|
|
5
|
+
const platform = navigator.userAgentData?.platform ??
|
|
6
|
+
navigator.platform;
|
|
7
|
+
return /mac|iphone|ipad|ipod/i.test(platform ?? '');
|
|
8
|
+
}
|
|
9
|
+
function parse(shortcut, apple) {
|
|
10
|
+
const parts = shortcut.split('+');
|
|
11
|
+
const key = parts.pop() ?? '';
|
|
12
|
+
const modifiers = new Set(parts.map((m) => (m === 'Mod' ? (apple ? 'Meta' : 'Control') : m)));
|
|
13
|
+
return { key, modifiers };
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Whether a keydown is this shortcut. Modifiers must match exactly. Digits match by physical key,
|
|
17
|
+
* since Alt+1 types `¡` on a Mac; letters match by the character typed, falling back to the
|
|
18
|
+
* physical key on non-Latin layouts, so ⌘K still works with a Cyrillic layout on.
|
|
19
|
+
*/
|
|
20
|
+
export function matchesShortcut(e, shortcut, apple = isApplePlatform()) {
|
|
21
|
+
const { key, modifiers } = parse(shortcut, apple);
|
|
22
|
+
if (e.metaKey !== modifiers.has('Meta') ||
|
|
23
|
+
e.ctrlKey !== modifiers.has('Control') ||
|
|
24
|
+
e.altKey !== modifiers.has('Alt'))
|
|
25
|
+
return false;
|
|
26
|
+
const alphanumeric = /^[a-z0-9]$/i.test(key);
|
|
27
|
+
// Shift is part of typing a symbol like `?`, so it's only checked for letters and digits.
|
|
28
|
+
if (modifiers.has('Shift') ? !e.shiftKey : alphanumeric && e.shiftKey)
|
|
29
|
+
return false;
|
|
30
|
+
if (/^[0-9]$/.test(key))
|
|
31
|
+
return e.code === `Digit${key}` || e.code === `Numpad${key}`;
|
|
32
|
+
if (/^[a-z]$/i.test(key)) {
|
|
33
|
+
return /^[a-z]$/i.test(e.key)
|
|
34
|
+
? e.key.toLowerCase() === key.toLowerCase()
|
|
35
|
+
: e.code === `Key${key.toUpperCase()}`;
|
|
36
|
+
}
|
|
37
|
+
return e.key === key;
|
|
38
|
+
}
|
|
39
|
+
/** Whether a keydown's target takes text, where a bare `/` is typing, not a shortcut. */
|
|
40
|
+
export function isEditableTarget(target) {
|
|
41
|
+
if (!(target instanceof HTMLElement))
|
|
42
|
+
return false;
|
|
43
|
+
if (target.isContentEditable || target instanceof HTMLTextAreaElement)
|
|
44
|
+
return true;
|
|
45
|
+
if (target instanceof HTMLSelectElement)
|
|
46
|
+
return true;
|
|
47
|
+
return (target instanceof HTMLInputElement &&
|
|
48
|
+
!/^(button|checkbox|color|file|hidden|image|radio|range|reset|submit)$/.test(target.type));
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Whether a page-wide shortcut should fire for this keydown: it matches, nothing handled the key
|
|
52
|
+
* first, no IME is composing, a shortcut without ⌘/Ctrl/Alt isn't being typed into a field, and
|
|
53
|
+
* no modal dialog other than the one holding `owner` is open.
|
|
54
|
+
*/
|
|
55
|
+
export function triggersShortcut(e, shortcut, owner) {
|
|
56
|
+
if (!shortcut || e.defaultPrevented || e.isComposing || e.repeat)
|
|
57
|
+
return false;
|
|
58
|
+
if (!matchesShortcut(e, shortcut))
|
|
59
|
+
return false;
|
|
60
|
+
if (!/(^|\+)(Mod|Meta|Control|Alt)\+/.test(shortcut) && isEditableTarget(e.target))
|
|
61
|
+
return false;
|
|
62
|
+
const modal = document.querySelector('[aria-modal="true"]');
|
|
63
|
+
return !modal || (!!owner && modal.contains(owner));
|
|
64
|
+
}
|
|
65
|
+
/** The shortcut for `aria-keyshortcuts`, with `Mod` resolved for this platform. */
|
|
66
|
+
export function ariaKeyShortcut(shortcut, apple = isApplePlatform()) {
|
|
67
|
+
const { key, modifiers } = parse(shortcut, apple);
|
|
68
|
+
return [...modifiers, key.length === 1 ? key.toUpperCase() : key].join('+');
|
|
69
|
+
}
|
|
70
|
+
const SYMBOLS = { Meta: '⌘', Control: '⌃', Alt: '⌥', Shift: '⇧' };
|
|
71
|
+
const NAMES = {
|
|
72
|
+
Meta: 'Win',
|
|
73
|
+
Control: 'Ctrl',
|
|
74
|
+
Alt: 'Alt',
|
|
75
|
+
Shift: 'Shift'
|
|
76
|
+
};
|
|
77
|
+
/** The shortcut as people read it on this platform: `⌘K` on a Mac, `Ctrl+K` elsewhere. */
|
|
78
|
+
export function shortcutLabel(shortcut, apple = isApplePlatform()) {
|
|
79
|
+
const { key, modifiers } = parse(shortcut, apple);
|
|
80
|
+
const k = key.length === 1 ? key.toUpperCase() : key;
|
|
81
|
+
return apple
|
|
82
|
+
? [...modifiers].map((m) => SYMBOLS[m]).join('') + k
|
|
83
|
+
: [...[...modifiers].map((m) => NAMES[m]), k].join('+');
|
|
84
|
+
}
|