Merge pull request #76 from IBM/refactor

refactor: use onMount, afterUpdate methods to manage state
This commit is contained in:
Eric Liu 2019-12-25 07:27:54 -08:00 committed by GitHub
commit 25cd26af24
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
14 changed files with 97 additions and 88 deletions

View file

@ -11,6 +11,7 @@
export let light = false; export let light = false;
export let style = undefined; export let style = undefined;
import { afterUpdate } from 'svelte';
import ChevronDown16 from 'carbon-icons-svelte/lib/ChevronDown16'; import ChevronDown16 from 'carbon-icons-svelte/lib/ChevronDown16';
import { cx } from '../../lib'; import { cx } from '../../lib';
import Button from '../Button'; import Button from '../Button';
@ -22,10 +23,11 @@
let expanded = false; let expanded = false;
let showMoreLess = false; let showMoreLess = false;
$: expandText = expanded ? showLessText : showMoreText; afterUpdate(() => {
$: if (codeRef) {
showMoreLess = type === 'multi' && codeRef.getBoundingClientRect().height > 255; showMoreLess = type === 'multi' && codeRef.getBoundingClientRect().height > 255;
} });
$: expandText = expanded ? showLessText : showMoreText;
</script> </script>
{#if type === 'inline'} {#if type === 'inline'}

View file

@ -8,7 +8,7 @@
export let size = undefined; export let size = undefined;
export let style = undefined; export let style = undefined;
import { createEventDispatcher, setContext, onDestroy } from 'svelte'; import { createEventDispatcher, tick, setContext, onMount, afterUpdate } from 'svelte';
import { writable } from 'svelte/store'; import { writable } from 'svelte/store';
import { cx } from '../../lib'; import { cx } from '../../lib';
@ -30,10 +30,6 @@
} }
}); });
onDestroy(() => {
document.body.classList.remove(cx('--body--with-modal-open'));
});
function focus(element) { function focus(element) {
if (element.querySelector(selectorPrimaryFocus)) { if (element.querySelector(selectorPrimaryFocus)) {
return focusElement.focus(); return focusElement.focus();
@ -44,10 +40,18 @@
} }
} }
$: didOpen = open; onMount(async () => {
$: { await tick();
if (innerModal) { focus(innerModal);
focus(innerModal);
return () => {
document.body.classList.remove(cx('--body--with-modal-open'));
};
});
afterUpdate(() => {
if (!didOpen) {
focus(outerModal);
} }
if (open) { if (open) {
@ -56,7 +60,9 @@
dispatch('close'); dispatch('close');
document.body.classList.remove(cx('--body--with-modal-open')); document.body.classList.remove(cx('--body--with-modal-open'));
} }
} });
$: didOpen = open;
</script> </script>
<div <div
@ -76,7 +82,6 @@
on:transitionend on:transitionend
on:transitionend={() => { on:transitionend={() => {
if (didOpen) { if (didOpen) {
focus(outerModal);
didOpen = false; didOpen = false;
} }
}} }}

View file

@ -6,8 +6,8 @@
export let disabled = false; export let disabled = false;
export let style = undefined; export let style = undefined;
import { afterUpdate, getContext } from 'svelte';
import { cx } from '../../lib'; import { cx } from '../../lib';
import { getContext } from 'svelte';
const id = Math.random(); const id = Math.random();
const { currentId, add, update, change } = getContext('ContentSwitcher'); const { currentId, add, update, change } = getContext('ContentSwitcher');
@ -16,10 +16,13 @@
add({ id, text, selected }); add({ id, text, selected });
afterUpdate(() => {
if (selected) {
buttonRef.focus();
}
});
$: selected = $currentId === id; $: selected = $currentId === id;
$: if (selected && buttonRef) {
buttonRef.focus();
}
</script> </script>
<button <button
@ -36,10 +39,10 @@
on:mouseenter on:mouseenter
on:mouseleave on:mouseleave
on:keydown on:keydown
on:keydown={event => { on:keydown={({ key }) => {
if (event.key === 'ArrowRight') { if (key === 'ArrowRight') {
change(1); change(1);
} else if (event.key === 'ArrowLeft') { } else if (key === 'ArrowLeft') {
change(-1); change(-1);
} }
}} }}

View file

@ -11,10 +11,8 @@
let timeoutId = undefined; let timeoutId = undefined;
onDestroy(() => { onDestroy(() => {
if (timeoutId !== undefined) { window.clearTimeout(timeoutId);
window.clearTimeout(timeoutId); timeoutId = undefined;
timeoutId = undefined;
}
}); });
$: showFeedback = timeoutId !== undefined; $: showFeedback = timeoutId !== undefined;

View file

@ -6,19 +6,25 @@
export let feedbackTimeout = 2000; export let feedbackTimeout = 2000;
export let style = undefined; export let style = undefined;
import { onDestroy } from 'svelte'; import { afterUpdate, onDestroy } from 'svelte';
import Copy16 from 'carbon-icons-svelte/lib/Copy16'; import Copy16 from 'carbon-icons-svelte/lib/Copy16';
import { cx } from '../../lib'; import { cx } from '../../lib';
let animation = undefined; let animation = undefined;
let timeoutId = undefined; let timeoutId = undefined;
onDestroy(() => { afterUpdate(() => {
if (timeoutId !== undefined) { if (animation === 'fade-in') {
window.clearTimeout(timeoutId); timeoutId = window.setTimeout(() => {
timeoutId = undefined; animation = 'fade-out';
}, feedbackTimeout);
} }
}); });
onDestroy(() => {
window.clearTimeout(timeoutId);
timeoutId = undefined;
});
</script> </script>
<button <button
@ -30,9 +36,6 @@
on:click on:click
on:click={() => { on:click={() => {
animation = 'fade-in'; animation = 'fade-in';
timeoutId = window.setTimeout(() => {
animation = 'fade-out';
}, feedbackTimeout);
}} }}
on:mouseover on:mouseover
on:mouseenter on:mouseenter

View file

@ -10,6 +10,7 @@
import FileUploaderDropContainer from './FileUploaderDropContainer.svelte'; import FileUploaderDropContainer from './FileUploaderDropContainer.svelte';
import FileUploaderSkeleton from './FileUploader.Skeleton.svelte'; import FileUploaderSkeleton from './FileUploader.Skeleton.svelte';
let fileUploader = undefined;
let files = []; let files = [];
$: disabled = files.length === 0; $: disabled = files.length === 0;
@ -37,6 +38,7 @@
{:else if story === 'uploader'} {:else if story === 'uploader'}
<div class={cx('--file__container')}> <div class={cx('--file__container')}>
<FileUploader <FileUploader
bind:this={fileUploader}
{...$$props} {...$$props}
bind:files bind:files
on:add={({ detail }) => { on:add={({ detail }) => {
@ -50,9 +52,7 @@
size="small" size="small"
style="margin-top: 1rem" style="margin-top: 1rem"
{disabled} {disabled}
on:click={() => { on:click={fileUploader.clearFiles}>
files = [];
}}>
Clear File{files.length === 1 ? '' : 's'} Clear File{files.length === 1 ? '' : 's'}
</Button> </Button>
</div> </div>

View file

@ -2,6 +2,7 @@
let className = undefined; let className = undefined;
export { className as class }; export { className as class };
export let files = []; export let files = [];
export const clearFiles = () => (files = []);
export let name = ''; export let name = '';
export let labelDescription = ''; export let labelDescription = '';
export let labelTitle = ''; export let labelTitle = '';
@ -13,7 +14,7 @@
export let accept = []; export let accept = [];
export let style = undefined; export let style = undefined;
import { createEventDispatcher } from 'svelte'; import { createEventDispatcher, afterUpdate } from 'svelte';
import { cx } from '../../lib'; import { cx } from '../../lib';
import Filename from './Filename.svelte'; import Filename from './Filename.svelte';
import FileUploaderButton from './FileUploaderButton.svelte'; import FileUploaderButton from './FileUploaderButton.svelte';
@ -22,7 +23,7 @@
let prevFiles = []; let prevFiles = [];
$: { afterUpdate(() => {
if (files.length > prevFiles.length) { if (files.length > prevFiles.length) {
dispatch('add', files); dispatch('add', files);
} else { } else {
@ -33,7 +34,7 @@
} }
prevFiles = [...files]; prevFiles = [...files];
} });
</script> </script>
<div on:click on:mouseover on:mouseenter on:mouseleave class={cx('--form-item', className)} {style}> <div on:click on:mouseover on:mouseenter on:mouseleave class={cx('--form-item', className)} {style}>

View file

@ -21,9 +21,6 @@
let over = false; let over = false;
let inputRef = undefined; let inputRef = undefined;
$: _class = cx('--file__drop-container', over && '--file__drop-container--drag-over', className);
$: _labelClass = cx('--file-browse-btn', disabled && '--file-browse-btn--disabled');
</script> </script>
<div <div
@ -51,7 +48,7 @@
}} }}
{style}> {style}>
<label <label
class={_labelClass} class={cx('--file-browse-btn', disabled && '--file-browse-btn--disabled')}
for={id} for={id}
on:keydown on:keydown
on:keydown={({ key }) => { on:keydown={({ key }) => {
@ -60,7 +57,9 @@
} }
}} }}
{tabindex}> {tabindex}>
<div class={_class} {role}> <div
class={cx('--file__drop-container', over && '--file__drop-container--drag-over', className)}
{role}>
{labelText} {labelText}
<input <input
bind:this={inputRef} bind:this={inputRef}

View file

@ -7,7 +7,7 @@
export let successDelay = 1500; export let successDelay = 1500;
export let style = undefined; export let style = undefined;
import { createEventDispatcher, onDestroy } from 'svelte'; import { createEventDispatcher, afterUpdate, onDestroy } from 'svelte';
import CheckmarkFilled16 from 'carbon-icons-svelte/lib/CheckmarkFilled16'; import CheckmarkFilled16 from 'carbon-icons-svelte/lib/CheckmarkFilled16';
import Error20 from 'carbon-icons-svelte/lib/Error20'; import Error20 from 'carbon-icons-svelte/lib/Error20';
import { cx } from '../../lib'; import { cx } from '../../lib';
@ -17,18 +17,18 @@
let timeoutId = undefined; let timeoutId = undefined;
onDestroy(() => { afterUpdate(() => {
if (timeoutId !== undefined) { if (status === 'finished') {
window.clearTimeout(timeoutId); timeoutId = window.setTimeout(() => {
timeoutId = undefined; dispatch('success');
}, successDelay);
} }
}); });
$: if (status === 'finished') { onDestroy(() => {
timeoutId = window.setTimeout(() => { window.clearTimeout(timeoutId);
dispatch('success'); timeoutId = undefined;
}, successDelay); });
}
</script> </script>
<div <div

View file

@ -21,14 +21,20 @@
const dispatch = createEventDispatcher(); const dispatch = createEventDispatcher();
let timeoutId = undefined;
let open = true; let open = true;
onMount(() => { onMount(() => {
if (timeout) { if (timeout) {
window.setTimeout(() => { timeoutId = window.setTimeout(() => {
open = false; open = false;
}, timeout); }, timeout);
} }
return () => {
window.clearTimeout(timeoutId);
timeoutId = undefined;
};
}); });
$: if (!open) { $: if (!open) {

View file

@ -2,6 +2,7 @@
let className = undefined; let className = undefined;
export { className as class }; export { className as class };
export let value = ''; export let value = '';
export let autofocus = false;
export let type = 'text'; export let type = 'text';
export let small = false; export let small = false;
export let placeHolderText = ''; export let placeHolderText = '';
@ -28,6 +29,7 @@
{style}> {style}>
<Search16 class={cx('--search-magnifier')} /> <Search16 class={cx('--search-magnifier')} />
<label for={id} class={cx('--label')}>{labelText}</label> <label for={id} class={cx('--label')}>{labelText}</label>
<!-- svelte-ignore a11y-autofocus -->
<input <input
bind:this={inputRef} bind:this={inputRef}
role="searchbox" role="searchbox"
@ -35,9 +37,10 @@
placeholder={placeHolderText} placeholder={placeHolderText}
on:change on:change
on:input on:input
on:input={event => { on:input={({ target }) => {
value = event.target.value; value = target.value;
}} }}
{autofocus}
{type} {type}
{id} {id}
{value} /> {value} />

View file

@ -11,7 +11,7 @@
export let light = false; export let light = false;
export let style = undefined; export let style = undefined;
import { tick } from 'svelte'; import { onMount, afterUpdate } from 'svelte';
import ChevronDown16 from 'carbon-icons-svelte/lib/ChevronDown16'; import ChevronDown16 from 'carbon-icons-svelte/lib/ChevronDown16';
import { cx, css } from '../../lib'; import { cx, css } from '../../lib';
@ -19,23 +19,20 @@
let tileContent = undefined; let tileContent = undefined;
let aboveTheFold = undefined; let aboveTheFold = undefined;
async function setHeight() { onMount(() => {
await tick(); const style = window.getComputedStyle(tile);
tileMaxHeight = aboveTheFold.getBoundingClientRect().height;
tilePadding =
parseInt(style.getPropertyValue('padding-top'), 10) +
parseInt(style.getPropertyValue('padding-bottom'), 10);
});
afterUpdate(() => {
tileMaxHeight = expanded tileMaxHeight = expanded
? tileContent.getBoundingClientRect().height ? tileContent.getBoundingClientRect().height
: aboveTheFold.getBoundingClientRect().height; : aboveTheFold.getBoundingClientRect().height;
} });
$: {
if (tile) {
const style = window.getComputedStyle(tile);
tileMaxHeight = aboveTheFold.getBoundingClientRect().height;
tilePadding =
parseInt(style.getPropertyValue('padding-top'), 10) +
parseInt(style.getPropertyValue('padding-bottom'), 10);
}
}
</script> </script>
<div <div
@ -45,14 +42,12 @@
on:click on:click
on:click={() => { on:click={() => {
expanded = !expanded; expanded = !expanded;
setHeight();
}} }}
on:keypress on:keypress
on:keypress={event => { on:keypress={event => {
if (event.key === ' ' || event.key === 'Enter') { if (event.key === ' ' || event.key === 'Enter') {
event.preventDefault(); event.preventDefault();
expanded = !expanded; expanded = !expanded;
setHeight();
} }
}} }}
on:mouseover on:mouseover

View file

@ -9,20 +9,17 @@
export let labelB = 'On'; export let labelB = 'On';
export let style = undefined; export let style = undefined;
import { createEventDispatcher } from 'svelte'; import { createEventDispatcher, afterUpdate } from 'svelte';
import { cx } from '../../lib'; import { cx } from '../../lib';
const dispatch = createEventDispatcher(); const dispatch = createEventDispatcher();
let inputRef = undefined; let inputRef = undefined;
$: { afterUpdate(() => {
inputRef.checked = toggled;
dispatch('toggle', { id, toggled }); dispatch('toggle', { id, toggled });
});
if (inputRef) {
inputRef.checked = toggled;
}
}
</script> </script>
<div on:click on:mouseover on:mouseenter on:mouseleave class={cx('--form-item', className)} {style}> <div on:click on:mouseover on:mouseenter on:mouseleave class={cx('--form-item', className)} {style}>

View file

@ -9,20 +9,17 @@
export let labelB = 'On'; export let labelB = 'On';
export let style = undefined; export let style = undefined;
import { createEventDispatcher } from 'svelte'; import { createEventDispatcher, afterUpdate } from 'svelte';
import { cx } from '../../lib'; import { cx } from '../../lib';
const dispatch = createEventDispatcher(); const dispatch = createEventDispatcher();
let inputRef = undefined; let inputRef = undefined;
$: { afterUpdate(() => {
inputRef.checked = toggled;
dispatch('toggle', { id, toggled }); dispatch('toggle', { id, toggled });
});
if (inputRef) {
inputRef.checked = toggled;
}
}
</script> </script>
<div on:click on:mouseover on:mouseenter on:mouseleave class={cx('--form-item', className)} {style}> <div on:click on:mouseover on:mouseenter on:mouseleave class={cx('--form-item', className)} {style}>