Alignment with Carbon version 10.31 (#571)

* chore(deps-dev): upgrade carbon-components to v10.31.0

* fix(slider): use CSS to hide input if hideTextInput is true

* docs(slider): add hidden text input, invalid, disabled examples

* feat(tabs): support "container" type for TabsSkeleton

* chore(list-box): remove hotfix inline style to center dropdown chevron

* fix(number-input): use add, subtract icons and update markup

* feat(select): add warning state

* docs(select): add invalid state example

* docs(select): add helper text example

* fix(structured-list): add "rowgroup" role to StructuredListBody

* docs: release code snippet max-width

* docs(select): add skeleton hidden label example

* feat(popover): add Popover component

* feat(pagination): dispatch button click events to be consistent with PaginationNav

* fix(multi-select): type clear as a custom event

* docs(radio-button): add disabled buttons example

* chore(tabs): use absolute icon import

* fix(link): remove line breaks within anchor link

* docs(radio-button): adjust section copy verbiage

* chore(deps-dev): upgrade carbon-icons-svelte to v10.27

v10.27 uses the SvelteComponentTyped interface

* docs(accordion): adjust section title verbiage

* test(types): fix warnings from svelte-check

* fix(search): only set autofocus attribute if equals true

* feat(popover): add closeOnOutsideClick prop

* docs: style [data-outline] as relative positioned

* feat(context-menu): add initial ContextMenu

* feat(context-menu): annotate props, generate types

* feat(context-menu): add initial focus logic

* fix(context-menu): correctly tab in/out of nested menus

* chore(context-menu): update types

* fix(context-menu): obtain radio id from node directly

* docs(context-menu): add examples and test

* fix(context-menu): prevent default keydown behavior
This commit is contained in:
Eric Liu 2021-03-20 10:39:14 -07:00 committed by GitHub
commit 5fad0cb3c7
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
52 changed files with 1758 additions and 103 deletions

View file

@ -0,0 +1,130 @@
<script>
/**
* Set to `true` to open the menu
* Either `x` and `y` must be greater than zero
*/
export let open = false;
/** Specify the horizontal offset of the menu position */
export let x = 0;
/** Specify the vertical offset of the menu position */
export let y = 0;
/** Obtain a reference to the unordered list HTML element */
export let ref = null;
import {
setContext,
getContext,
afterUpdate,
createEventDispatcher,
} from "svelte";
import { writable } from "svelte/store";
const dispatch = createEventDispatcher();
const position = writable([x, y]);
const currentIndex = writable(-1);
const hasPopup = writable(false);
const ctx = getContext("ContextMenu");
let options = [];
let direction = 1;
let prevX = 0;
let prevY = 0;
let focusIndex = -1;
function close() {
open = false;
x = 0;
y = 0;
prevX = 0;
prevY = 0;
focusIndex = -1;
}
setContext("ContextMenu", {
currentIndex,
position,
close,
setPopup: (popup) => {
hasPopup.set(popup);
},
});
afterUpdate(() => {
if (open) {
options = [...ref.querySelectorAll("li[data-nested='false']")];
if (level === 1) {
if (prevX !== x || prevY !== y) ref.focus();
prevX = x;
prevY = y;
}
dispatch("open");
} else {
dispatch("close");
}
if (!$hasPopup && options[focusIndex]) options[focusIndex].focus();
});
$: level = !ctx ? 1 : 2;
$: currentIndex.set(focusIndex);
</script>
<svelte:window
on:contextmenu|preventDefault="{(e) => {
if (level > 1) return;
if (open || x === 0) x = e.x;
if (open || y === 0) y = e.y;
position.set([x, y]);
open = true;
}}"
on:click="{(e) => {
if (!open) return;
if (e.target.contains(ref)) close();
}}"
on:keydown="{(e) => {
if (open && e.key === 'Escape') close();
}}"
/>
<ul
bind:this="{ref}"
role="menu"
tabindex="-1"
data-direction="{direction}"
data-level="{level}"
class:bx--context-menu="{true}"
class:bx--context-menu--open="{open}"
class:bx--context-menu--invisible="{open && x === 0 && y === 0}"
class:bx--context-menu--root="{level === 1}"
{...$$restProps}
style="left: {x}px; top: {y}px; {$$restProps.style}"
on:click
on:click="{({ target }) => {
const closestOption = target.closest('[tabindex]');
if (closestOption && closestOption.getAttribute('role') !== 'menuitem') {
close();
}
}}"
on:keydown
on:keydown|preventDefault="{(e) => {
if ($hasPopup) return;
if (e.key === 'ArrowDown') {
if (focusIndex < options.length - 1) focusIndex++;
} else if (e.key === 'ArrowUp') {
if (focusIndex === -1) {
focusIndex = options.length - 1;
} else {
if (focusIndex > 0) focusIndex--;
}
}
}}"
>
<slot />
</ul>