|
7 | 7 | 'mdc-switch': true,
|
8 | 8 | 'mdc-switch--disabled': disabled,
|
9 | 9 | 'mdc-switch--checked': nativeChecked,
|
| 10 | + ...internalClasses, |
10 | 11 | })}
|
11 | 12 | {...exclude($$props, [
|
12 | 13 | 'use',
|
|
19 | 20 | ])}
|
20 | 21 | >
|
21 | 22 | <div class="mdc-switch__track" />
|
22 |
| - <div class="mdc-switch__thumb-underlay"> |
23 |
| - <div class="mdc-switch__thumb"> |
24 |
| - <input |
25 |
| - use:useActions={input$use} |
26 |
| - class={classMap({ |
27 |
| - [input$class]: true, |
28 |
| - 'mdc-switch__native-control': true, |
29 |
| - })} |
30 |
| - type="checkbox" |
31 |
| - role="switch" |
32 |
| - {...inputProps} |
33 |
| - {disabled} |
34 |
| - bind:checked={nativeChecked} |
35 |
| - value={valueKey === uninitializedValue ? value : valueKey} |
36 |
| - on:change={handleChange} |
37 |
| - on:change |
38 |
| - on:input |
39 |
| - on:blur |
40 |
| - on:focus |
41 |
| - {...exclude(prefixFilter($$props, 'input$'), ['use', 'class'])} |
42 |
| - /> |
43 |
| - </div> |
| 23 | + <div |
| 24 | + class={classMap({ |
| 25 | + 'mdc-switch__thumb-underlay': true, |
| 26 | + ...thumbUnderlayClasses, |
| 27 | + })} |
| 28 | + use:Ripple={{ |
| 29 | + unbounded: true, |
| 30 | + addClass: addThumbUnderlayClass, |
| 31 | + removeClass: removeThumbUnderlayClass, |
| 32 | + active: rippleActive, |
| 33 | + }} |
| 34 | + > |
| 35 | + <div class="mdc-switch__thumb" /> |
| 36 | + <input |
| 37 | + use:useActions={input$use} |
| 38 | + class={classMap({ |
| 39 | + [input$class]: true, |
| 40 | + 'mdc-switch__native-control': true, |
| 41 | + })} |
| 42 | + type="checkbox" |
| 43 | + role="switch" |
| 44 | + {...inputProps} |
| 45 | + {disabled} |
| 46 | + bind:checked={nativeChecked} |
| 47 | + aria-checked={nativeChecked ? 'true' : 'false'} |
| 48 | + value={valueKey === uninitializedValue ? value : valueKey} |
| 49 | + on:change={handleChange} |
| 50 | + on:change={(event) => instance && instance.handleChange(event)} |
| 51 | + on:change |
| 52 | + on:input |
| 53 | + on:blur |
| 54 | + on:focus |
| 55 | + {...internalAttrs} |
| 56 | + {...exclude(prefixFilter($$props, 'input$'), ['use', 'class'])} |
| 57 | + /> |
44 | 58 | </div>
|
45 | 59 | </div>
|
46 | 60 |
|
47 | 61 | <script>
|
48 |
| - import { MDCSwitch } from '@material/switch'; |
49 |
| - import { onMount, onDestroy, getContext } from 'svelte'; |
| 62 | + import { MDCSwitchFoundation } from '@material/switch'; |
| 63 | + import { onMount, getContext } from 'svelte'; |
50 | 64 | import { get_current_component } from 'svelte/internal';
|
51 | 65 | import {
|
52 | 66 | forwardEventsBuilder,
|
53 | 67 | classMap,
|
54 | 68 | exclude,
|
55 | 69 | prefixFilter,
|
56 | 70 | useActions,
|
| 71 | + dispatch, |
57 | 72 | } from '@smui/common/internal.js';
|
| 73 | + import Ripple from '@smui/ripple/bare.js'; |
58 | 74 |
|
59 |
| - const forwardEvents = forwardEventsBuilder(get_current_component()); |
| 75 | + const forwardEvents = forwardEventsBuilder(get_current_component(), [ |
| 76 | + 'SMUI:generic:input:mount', |
| 77 | + ]); |
60 | 78 | let uninitializedValue = () => {};
|
61 | 79 |
|
62 | 80 | export let use = [];
|
|
71 | 89 | export let input$class = '';
|
72 | 90 |
|
73 | 91 | let element;
|
74 |
| - let switchControl; |
75 |
| - let formField = getContext('SMUI:form-field'); |
| 92 | + let instance; |
| 93 | + let internalClasses = {}; |
| 94 | + let thumbUnderlayClasses = {}; |
| 95 | + // These are added to the native control, not `element`. |
| 96 | + let internalAttrs = {}; |
| 97 | + let rippleActive = false; |
76 | 98 | let inputProps = getContext('SMUI:generic:input:props') || {};
|
77 | 99 | let setChecked = getContext('SMUI:generic:input:setChecked');
|
78 | 100 | let nativeChecked =
|
|
82 | 104 | : checked
|
83 | 105 | : group.indexOf(value) !== -1;
|
84 | 106 |
|
85 |
| - $: if (switchControl && $formField && $formField.input !== switchControl) { |
86 |
| - $formField.input = switchControl; |
87 |
| - } |
88 |
| -
|
89 | 107 | $: if (setChecked) {
|
90 | 108 | setChecked(nativeChecked);
|
91 | 109 | }
|
92 | 110 |
|
93 |
| - $: if (switchControl) { |
94 |
| - if (group !== uninitializedValue) { |
95 |
| - const isChecked = group.indexOf(value) !== -1; |
96 |
| - if (switchControl.checked !== isChecked) { |
97 |
| - switchControl.checked = isChecked; |
98 |
| - } |
99 |
| - } else if ( |
100 |
| - checked !== uninitializedValue && |
101 |
| - switchControl.checked !== checked |
102 |
| - ) { |
103 |
| - switchControl.checked = checked; |
104 |
| - } |
105 |
| - } |
106 |
| -
|
107 |
| - $: if (switchControl && switchControl.disabled !== disabled) { |
108 |
| - switchControl.disabled = disabled; |
109 |
| - } |
110 |
| -
|
111 |
| - $: if ( |
112 |
| - switchControl && |
113 |
| - valueKey === uninitializedValue && |
114 |
| - switchControl.value !== value |
115 |
| - ) { |
116 |
| - switchControl.value = value; |
117 |
| - } |
118 |
| -
|
119 |
| - $: if ( |
120 |
| - switchControl && |
121 |
| - valueKey !== uninitializedValue && |
122 |
| - switchControl.value !== valueKey |
123 |
| - ) { |
124 |
| - switchControl.value = valueKey; |
125 |
| - } |
126 |
| -
|
127 | 111 | let previousChecked = checked;
|
128 | 112 | $: if (checked !== uninitializedValue) {
|
129 | 113 | if (checked === previousChecked) {
|
130 | 114 | checked = nativeChecked;
|
131 | 115 | } else if (nativeChecked !== checked) {
|
132 | 116 | nativeChecked = checked;
|
| 117 | + instance && instance.handleChange(); |
133 | 118 | }
|
134 | 119 | previousChecked = checked;
|
135 | 120 | }
|
136 | 121 |
|
137 | 122 | onMount(() => {
|
138 |
| - switchControl = new MDCSwitch(element); |
| 123 | + instance = new MDCSwitchFoundation({ |
| 124 | + addClass, |
| 125 | + removeClass, |
| 126 | + setNativeControlChecked: (checked) => (nativeChecked = checked), |
| 127 | + setNativeControlDisabled: (disabledValue) => (disabled = disabledValue), |
| 128 | + setNativeControlAttr: addAttr, |
| 129 | + }); |
| 130 | +
|
| 131 | + dispatch(element, 'SMUI:generic:input:mount', { |
| 132 | + get element() { |
| 133 | + return getElement(); |
| 134 | + }, |
| 135 | + get checked() { |
| 136 | + return nativeChecked; |
| 137 | + }, |
| 138 | + set checked(checked) { |
| 139 | + if (nativeChecked !== checked) { |
| 140 | + nativeChecked = checked; |
| 141 | + handleChange(); |
| 142 | + instance && instance.handleChange(); |
| 143 | + } |
| 144 | + }, |
| 145 | + activateRipple() { |
| 146 | + if (!disabled) { |
| 147 | + rippleActive = true; |
| 148 | + } |
| 149 | + }, |
| 150 | + deactivateRipple() { |
| 151 | + rippleActive = false; |
| 152 | + }, |
| 153 | + }); |
| 154 | +
|
| 155 | + instance.init(); |
| 156 | +
|
| 157 | + return () => { |
| 158 | + instance.destroy(); |
| 159 | + }; |
139 | 160 | });
|
140 | 161 |
|
141 |
| - onDestroy(() => { |
142 |
| - switchControl && switchControl.destroy(); |
143 |
| - }); |
| 162 | + function addClass(className) { |
| 163 | + if (!internalClasses[className]) { |
| 164 | + internalClasses[className] = true; |
| 165 | + } |
| 166 | + } |
| 167 | +
|
| 168 | + function removeClass(className) { |
| 169 | + if (!(className in internalClasses) || internalClasses[className]) { |
| 170 | + internalClasses[className] = false; |
| 171 | + } |
| 172 | + } |
| 173 | +
|
| 174 | + function addThumbUnderlayClass(className) { |
| 175 | + if (!thumbUnderlayClasses[className]) { |
| 176 | + thumbUnderlayClasses[className] = true; |
| 177 | + } |
| 178 | + } |
| 179 | +
|
| 180 | + function removeThumbUnderlayClass(className) { |
| 181 | + if ( |
| 182 | + !(className in thumbUnderlayClasses) || |
| 183 | + thumbUnderlayClasses[className] |
| 184 | + ) { |
| 185 | + thumbUnderlayClasses[className] = false; |
| 186 | + } |
| 187 | + } |
| 188 | +
|
| 189 | + function addAttr(name, value) { |
| 190 | + if (internalAttrs[name] !== value) { |
| 191 | + internalAttrs[name] = value; |
| 192 | + } |
| 193 | + } |
144 | 194 |
|
145 |
| - function handleChange(e) { |
| 195 | + function handleChange() { |
146 | 196 | if (group !== uninitializedValue) {
|
147 | 197 | const idx = group.indexOf(value);
|
148 |
| - if (switchControl.checked && idx === -1) { |
| 198 | + if (nativeChecked && idx === -1) { |
149 | 199 | group.push(value);
|
150 | 200 | group = group;
|
151 |
| - } else if (!switchControl.checked && idx !== -1) { |
| 201 | + } else if (!nativeChecked && idx !== -1) { |
152 | 202 | group.splice(idx, 1);
|
153 | 203 | group = group;
|
154 | 204 | }
|
|
0 commit comments