Skip to content

Commit 849e007

Browse files
committed
feat: updated List for MDC v10
1 parent 18023ec commit 849e007

File tree

3 files changed

+246
-56
lines changed

3 files changed

+246
-56
lines changed

packages/list/Item.svelte

+115-24
Original file line numberDiff line numberDiff line change
@@ -1,36 +1,75 @@
11
<svelte:component
22
this={component}
3-
bind:element={element}
4-
use={[[Ripple, {ripple, unbounded: false, color, disabled, addClass, removeClass}], forwardEvents, ...use]}
3+
bind:element
4+
use={[
5+
[
6+
Ripple,
7+
{ ripple, unbounded: false, color, disabled, addClass, removeClass },
8+
],
9+
forwardEvents,
10+
...use,
11+
]}
512
class="
613
mdc-list-item
714
{className}
8-
{internalClasses.join(' ')}
15+
{internalClasses.join(
16+
' '
17+
)}
918
{activated ? 'mdc-list-item--activated' : ''}
10-
{selected ? 'mdc-list-item--selected' : ''}
19+
{selected
20+
? 'mdc-list-item--selected'
21+
: ''}
1122
{disabled ? 'mdc-list-item--disabled' : ''}
12-
{(!nav && role === 'menuitem' && selected) ? 'mdc-menu-item--selected' : ''}
23+
{!nav &&
24+
role === 'menuitem' &&
25+
selected
26+
? 'mdc-menu-item--selected'
27+
: ''}
1328
"
14-
{...((nav && activated) ? {'aria-current': 'page'} : {})}
15-
{...(!nav ? {role} : {})}
16-
{...((!nav && role === 'option') ? {'aria-selected': (selected ? 'true' : 'false')} : {})}
17-
{...((!nav && (role === 'radio' || role === 'checkbox')) ? {'aria-checked': (checked ? 'true' : 'false')} : {})}
18-
{...(!nav ? {'aria-disabled': (disabled ? 'true' : 'false')} : {})}
29+
{...nav && activated ? { 'aria-current': 'page' } : {}}
30+
{...!nav ? { role } : {}}
31+
{...!nav && role === 'option'
32+
? { 'aria-selected': selected ? 'true' : 'false' }
33+
: {}}
34+
{...!nav && (role === 'radio' || role === 'checkbox')
35+
? { 'aria-checked': checked ? 'true' : 'false' }
36+
: {}}
37+
{...!nav ? { 'aria-disabled': disabled ? 'true' : 'false' } : {}}
1938
{tabindex}
2039
on:click={action}
2140
on:keydown={handleKeydown}
22-
{...exclude($$props, ['use', 'class', 'ripple', 'color', 'nonInteractive', 'activated', 'selected', 'disabled', 'tabindex', 'inputId'])}
23-
>{#if ripple}<span class="mdc-list-item__ripple"></span>{/if}<slot></slot></svelte:component>
41+
{...internalAttrs}
42+
{...exclude($$props, [
43+
'use',
44+
'class',
45+
'ripple',
46+
'color',
47+
'nonInteractive',
48+
'activated',
49+
'selected',
50+
'disabled',
51+
'tabindex',
52+
'inputId',
53+
])}
54+
>{#if ripple}<span class="mdc-list-item__ripple" />{/if}<slot
55+
/></svelte:component
56+
>
2457

2558
<script context="module">
2659
let counter = 0;
2760
</script>
2861

2962
<script>
30-
import {onMount, onDestroy, getContext, setContext, createEventDispatcher} from 'svelte';
31-
import {get_current_component} from 'svelte/internal';
32-
import {forwardEventsBuilder} from '@smui/common/forwardEvents.js';
33-
import {exclude} from '@smui/common/exclude.js';
63+
import {
64+
onMount,
65+
onDestroy,
66+
getContext,
67+
setContext,
68+
createEventDispatcher,
69+
} from 'svelte';
70+
import { get_current_component } from 'svelte/internal';
71+
import { forwardEventsBuilder } from '@smui/common/forwardEvents.js';
72+
import { exclude } from '@smui/common/exclude.js';
3473
import A from '@smui/common/A.svelte';
3574
import Span from '@smui/common/Span.svelte';
3675
import Li from '@smui/common/Li.svelte';
@@ -42,27 +81,47 @@
4281
4382
export let use = [];
4483
let className = '';
45-
export {className as class};
84+
export { className as class };
4685
export let ripple = true;
4786
export let color = null;
4887
export let nonInteractive = getContext('SMUI:list:nonInteractive');
4988
export let activated = false;
5089
export let role = getContext('SMUI:list:item:role');
5190
export let selected = false;
5291
export let disabled = false;
53-
export let tabindex = !nonInteractive && !disabled && (selected || checked) && '0' || '-1';
54-
export let inputId = 'SMUI-form-field-list-'+(counter++);
92+
export let tabindex =
93+
(!nonInteractive && !disabled && (selected || checked) && '0') || '-1';
94+
export let inputId = 'SMUI-form-field-list-' + counter++;
5595
// Purposely left out of props exclude.
5696
export let href = null;
5797
5898
let element;
5999
let internalClasses = [];
100+
let internalAttrs = {};
60101
let addTabindexIfNoItemsSelectedRaf;
102+
let accessor = {
103+
_smui_accessor: true,
104+
get element() {
105+
return element;
106+
},
107+
get selected() {
108+
return selected;
109+
},
110+
set selected(value) {
111+
selected = value;
112+
},
113+
addClass,
114+
removeClass,
115+
addAttr,
116+
removeAttr,
117+
getPrimaryText,
118+
};
61119
let nav = getContext('SMUI:list:item:nav');
120+
let list = getContext('SMUI:list:instance');
62121
63122
export let component = nav ? (href ? A : Span) : Li;
64123
65-
setContext('SMUI:generic:input:props', {id: inputId});
124+
setContext('SMUI:generic:input:props', { id: inputId });
66125
setContext('SMUI:generic:input:setChecked', setChecked);
67126
68127
onMount(() => {
@@ -74,23 +133,33 @@
74133
let el = element;
75134
while (el.previousSibling) {
76135
el = el.previousSibling;
77-
if (el.nodeType === 1 && el.classList.contains('mdc-list-item') && !el.classList.contains('mdc-list-item--disabled')) {
136+
if (
137+
el.nodeType === 1 &&
138+
el.classList.contains('mdc-list-item') &&
139+
!el.classList.contains('mdc-list-item--disabled')
140+
) {
78141
first = false;
79142
break;
80143
}
81144
}
82145
if (first) {
83146
// This is first, so now set up a check that no other items are
84147
// selected.
85-
addTabindexIfNoItemsSelectedRaf = window.requestAnimationFrame(addTabindexIfNoItemsSelected);
148+
addTabindexIfNoItemsSelectedRaf = window.requestAnimationFrame(
149+
addTabindexIfNoItemsSelected
150+
);
86151
}
87152
}
153+
154+
dispatch('SMUI:list:item:mount', accessor);
88155
});
89156
90157
onDestroy(() => {
91158
if (addTabindexIfNoItemsSelectedRaf) {
92159
window.cancelAnimationFrame(addTabindexIfNoItemsSelectedRaf);
93160
}
161+
162+
dispatch('SMUI:list:item:unmount', accessor);
94163
});
95164
96165
function addClass(className) {
@@ -107,13 +176,34 @@
107176
}
108177
}
109178
179+
function addAttr(name, value) {
180+
internalAttrs[name] = value;
181+
}
182+
183+
function removeAttr(name) {
184+
delete internalAttrs[name];
185+
}
186+
187+
function getPrimaryText() {
188+
const primaryText = element.querySelector('.mdc-list-item__primary-text');
189+
if (primaryText) {
190+
return primaryText.textContent;
191+
}
192+
return '';
193+
}
194+
110195
function addTabindexIfNoItemsSelected() {
111196
// Look through next siblings to see if none of them are selected.
112197
let noneSelected = true;
113198
let el = element;
114199
while (el.nextSibling) {
115200
el = el.nextSibling;
116-
if (el.nodeType === 1 && el.classList.contains('mdc-list-item') && el.attributes['tabindex'] && el.attributes['tabindex'].value === '0') {
201+
if (
202+
el.nodeType === 1 &&
203+
el.classList.contains('mdc-list-item') &&
204+
el.attributes['tabindex'] &&
205+
el.attributes['tabindex'].value === '0'
206+
) {
117207
noneSelected = false;
118208
break;
119209
}
@@ -143,6 +233,7 @@
143233
144234
function setChecked(isChecked) {
145235
checked = isChecked;
146-
tabindex = !nonInteractive && !disabled && (selected || checked) && '0' || '-1';
236+
tabindex =
237+
(!nonInteractive && !disabled && (selected || checked) && '0') || '-1';
147238
}
148239
</script>

0 commit comments

Comments
 (0)