@shortfuse/materialdesignweb 0.7.6 → 0.8.0

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.
Files changed (114) hide show
  1. package/README.md +57 -68
  2. package/components/Badge.js +2 -2
  3. package/components/BottomAppBar.js +3 -5
  4. package/components/Box.js +33 -3
  5. package/components/Button.js +48 -21
  6. package/components/Button.md +9 -9
  7. package/components/Card.js +9 -16
  8. package/components/Checkbox.js +45 -36
  9. package/components/CheckboxIcon.js +2 -2
  10. package/components/Chip.js +1 -1
  11. package/components/Dialog.js +228 -359
  12. package/components/DialogActions.js +2 -2
  13. package/components/Divider.js +3 -3
  14. package/components/ExtendedFab.js +4 -8
  15. package/components/Fab.js +1 -2
  16. package/components/FilterChip.js +4 -4
  17. package/components/Headline.js +1 -1
  18. package/components/Icon.js +8 -8
  19. package/components/IconButton.js +9 -14
  20. package/components/Input.js +273 -1
  21. package/components/Layout.js +485 -16
  22. package/components/List.js +6 -4
  23. package/components/ListItem.js +12 -12
  24. package/components/ListOption.js +21 -5
  25. package/components/Listbox.js +239 -0
  26. package/components/Menu.js +77 -526
  27. package/components/MenuItem.js +12 -14
  28. package/components/Nav.js +0 -2
  29. package/components/NavBar.js +8 -79
  30. package/components/NavDrawer.js +12 -11
  31. package/components/NavDrawerItem.js +2 -1
  32. package/components/NavItem.js +18 -8
  33. package/components/NavRail.js +15 -7
  34. package/components/NavRailItem.js +3 -1
  35. package/components/Popup.js +20 -0
  36. package/components/Progress.js +24 -23
  37. package/components/Radio.js +42 -35
  38. package/components/RadioIcon.js +3 -3
  39. package/components/Ripple.js +2 -3
  40. package/components/Search.js +85 -0
  41. package/components/SegmentedButton.js +1 -10
  42. package/components/SegmentedButtonGroup.js +16 -10
  43. package/components/Select.js +4 -4
  44. package/components/Shape.js +1 -1
  45. package/components/Slider.js +43 -50
  46. package/components/Snackbar.js +4 -5
  47. package/components/Surface.js +3 -3
  48. package/components/Switch.js +55 -21
  49. package/components/SwitchIcon.js +10 -8
  50. package/components/Tab.js +11 -9
  51. package/components/TabContent.js +4 -3
  52. package/components/TabList.js +2 -2
  53. package/components/TabPanel.js +11 -8
  54. package/components/TextArea.js +38 -35
  55. package/components/Tooltip.js +2 -2
  56. package/components/TopAppBar.js +65 -147
  57. package/core/Composition.js +985 -628
  58. package/core/CompositionAdapter.js +315 -0
  59. package/core/CustomElement.js +153 -90
  60. package/core/DomAdapter.js +586 -0
  61. package/core/ICustomElement.d.ts +2 -2
  62. package/core/css.js +8 -7
  63. package/core/customTypes.js +53 -31
  64. package/{utils → core}/jsonMergePatch.js +36 -14
  65. package/core/observe.js +111 -57
  66. package/core/optimizations.js +23 -0
  67. package/core/template.js +17 -11
  68. package/core/test.js +126 -0
  69. package/core/typings.d.ts +11 -5
  70. package/core/uid.js +13 -0
  71. package/dist/index.min.js +83 -152
  72. package/dist/index.min.js.map +4 -4
  73. package/dist/meta.json +1 -1
  74. package/mixins/AriaReflectorMixin.js +1 -2
  75. package/mixins/AriaToolbarMixin.js +2 -3
  76. package/mixins/ControlMixin.js +25 -17
  77. package/mixins/DensityMixin.js +0 -1
  78. package/mixins/FlexableMixin.js +1 -2
  79. package/mixins/FormAssociatedMixin.js +13 -10
  80. package/mixins/InputMixin.js +2 -9
  81. package/mixins/KeyboardNavMixin.js +14 -1
  82. package/mixins/PopupMixin.js +757 -0
  83. package/mixins/RTLObserverMixin.js +0 -1
  84. package/mixins/ResizeObserverMixin.js +0 -1
  85. package/mixins/RippleMixin.js +3 -4
  86. package/mixins/ScrollListenerMixin.js +41 -32
  87. package/mixins/SemiStickyMixin.js +151 -0
  88. package/mixins/ShapeMixin.js +29 -24
  89. package/mixins/StateMixin.js +11 -6
  90. package/mixins/SurfaceMixin.js +3 -57
  91. package/mixins/TextFieldMixin.js +57 -65
  92. package/mixins/ThemableMixin.js +78 -156
  93. package/mixins/TooltipTriggerMixin.js +7 -13
  94. package/mixins/TouchTargetMixin.js +4 -3
  95. package/package.json +9 -5
  96. package/theming/index.js +1 -1
  97. package/theming/themableMixinLoader.js +12 -0
  98. package/utils/{hct → material-color}/blend.js +8 -10
  99. package/utils/{hct → material-color/hct}/Cam16.js +196 -69
  100. package/utils/{hct → material-color/hct}/Hct.js +61 -19
  101. package/utils/{hct → material-color/hct}/ViewingConditions.js +3 -3
  102. package/utils/{hct → material-color/hct}/hctSolver.js +9 -16
  103. package/utils/{hct → material-color}/helper.js +11 -18
  104. package/utils/{hct → material-color/palettes}/CorePalette.js +79 -19
  105. package/utils/{hct → material-color/palettes}/TonalPalette.js +12 -4
  106. package/utils/material-color/scheme/Scheme.js +376 -0
  107. package/utils/{hct/colorUtils.js → material-color/utils/color.js} +61 -1
  108. package/utils/popup.js +46 -25
  109. package/components/ListSelect.js +0 -220
  110. package/components/Option.js +0 -91
  111. package/components/Pane.js +0 -281
  112. package/core/identify.js +0 -40
  113. package/utils/hct/Scheme.js +0 -587
  114. /package/utils/{hct/mathUtils.js → material-color/utils/math.js} +0 -0
@@ -0,0 +1,315 @@
1
+ import { createEmptyComment } from './optimizations.js';
2
+
3
+ /**
4
+ * @typedef {Object} DomAdapterCreateOptions
5
+ * @prop {Comment} anchorNode
6
+ * @prop {(...args:any[]) => HTMLElement} [create]
7
+ */
8
+
9
+ /**
10
+ * @typedef {Object} ItemMetadata
11
+ * @prop {Element} element
12
+ * @prop {any} key
13
+ * @prop {Element|Comment} domNode
14
+ * @prop {Function} render
15
+ * @prop {boolean} [hidden]
16
+ * @prop {Comment} [comment]
17
+ */
18
+
19
+ export default class CompositionAdapter {
20
+ /** @param {DomAdapterCreateOptions} options */
21
+ constructor(options) {
22
+ this.anchorNode = options.anchorNode;
23
+
24
+ /** @type {ItemMetadata[]} */
25
+ this.metadata = [];
26
+ /**
27
+ * Ordered-list of metadata keys
28
+ * Chrome and FireFox optimize arrays for indexOf/includes
29
+ * Safari is faster with WeakMap.get(), but can't use Primitive keys
30
+ * TODO: Add Safari path
31
+ * @type {any[]}
32
+ */
33
+ this.keys = [];
34
+
35
+ /**
36
+ * Chrome needs a hint to know we will need a fast path for array by keys.
37
+ */
38
+ this.needsArrayKeyFastPath = false;
39
+
40
+ this.composition = options.composition;
41
+ this.renderOptions = options.renderOptions;
42
+
43
+ this.pendingRemoves = [];
44
+ // Batch objects
45
+
46
+ /** @type {Map<any, ItemMetadata>} */
47
+ this.metadataCache = null;
48
+
49
+ /** @type {Element[]} */
50
+ this.queuedElements = [];
51
+ // this.batching = false;
52
+ /** @type {number|null} */
53
+ this.batchStartIndex = null;
54
+ /** @type {number|null} */
55
+ this.batchEndIndex = null;
56
+ }
57
+
58
+ render(changes, data) {
59
+ return this.composition.render(changes, data, this.renderOptions);
60
+ }
61
+
62
+ startBatch() {
63
+ this.needsArrayKeyFastPath = true;
64
+ // this.batching = true;
65
+ }
66
+
67
+ writeBatch() {
68
+ if (!this.queuedElements.length) return;
69
+ /** @type {Comment|Element} */
70
+ const previousSibling = this.metadata[this.batchStartIndex - 1]?.domNode ?? this.anchorNode;
71
+ previousSibling.after(...this.queuedElements);
72
+ this.queuedElements.length = 0;
73
+ }
74
+
75
+ stopBatch() {
76
+ this.writeBatch();
77
+
78
+ this.needsArrayKeyFastPath = false;
79
+ this.batchStartIndex = null;
80
+ this.batchEndIndex = null;
81
+ if (this.metadataCache !== null) {
82
+ for (const { domNode } of this.metadataCache.values()) {
83
+ domNode.remove();
84
+ }
85
+ this.metadataCache.clear();
86
+ }
87
+ }
88
+
89
+ /** @param {number} index */
90
+ removeByIndex(index) {
91
+ const [metadata] = this.metadata.splice(index, 1);
92
+ const { domNode, key } = metadata;
93
+ this.keys.splice(index, 1);
94
+ domNode.remove();
95
+
96
+ // Don't release in case we may need it later
97
+ if (this.metadataCache === null) {
98
+ this.metadataCache = new Map([[key, metadata]]);
99
+ } else {
100
+ this.metadataCache.set(key, metadata);
101
+ }
102
+ }
103
+
104
+ /**
105
+ * Worst case scenario
106
+ * @param {number} newIndex expectedIndex
107
+ * @param {*} changes
108
+ * @param {*} data
109
+ * @param {*} key
110
+ * @param {*} change
111
+ * @param {boolean} [skipOnMatch]
112
+ * JSON Merge has no way to express sort change and data change. Best
113
+ * performance is done via invoking render on sort change and another on
114
+ * inner change. Can't skip if mixing change types.
115
+ */
116
+ renderData(newIndex, changes, data, key, change, skipOnMatch) {
117
+ if (newIndex < this.metadata.length) {
118
+ const metadataAtIndex = this.metadata[newIndex];
119
+
120
+ // There is an element in this slot
121
+
122
+ // Compare if different
123
+ const currentKey = metadataAtIndex.key;
124
+ const sameKey = (currentKey === key);
125
+ const isPartial = (change !== key);
126
+
127
+ if (sameKey) {
128
+ // Both reference the same key (correct spot)
129
+ if (isPartial) {
130
+ metadataAtIndex.render(changes, data);
131
+ } else if (skipOnMatch) {
132
+ // Skip overwrite. Presume no change
133
+ // console.warn('same key, no reason to repaint', newIndex);
134
+ } else {
135
+ // console.warn('no skip on match', newIndex);
136
+ metadataAtIndex.render(changes, data);
137
+ }
138
+ return;
139
+ }
140
+
141
+ if (this.metadataCache === null) {
142
+ this.metadataCache = new Map();
143
+ }
144
+
145
+ // If not same key. Scan key list.
146
+ // Can avoid checking before current index. Will always be after current
147
+ let failedFastPath = false;
148
+ if (this.needsArrayKeyFastPath) {
149
+ // Invoking includes will ensure Chrome generates an internal hash map
150
+ failedFastPath = !this.keys.includes(key);
151
+ this.needsArrayFastPath = false;
152
+ }
153
+ const oldIndex = failedFastPath ? -1 : this.keys.indexOf(key, newIndex + 1);
154
+ if (oldIndex === -1) {
155
+ // New key
156
+ // console.log('new key?', 'should be at', newIndex);
157
+ // Was key removed in this batch?
158
+ if (this.metadataCache.has(key)) {
159
+ // console.log('inserting removed element', 'at', newIndex);
160
+ // (Optimistic insert)
161
+ // Key was removed and should be here instead
162
+ // If should have been replace, will correct next step
163
+ const previousMetadata = this.metadataCache.get(key);
164
+ this.metadata.splice(newIndex, 0, previousMetadata);
165
+ this.keys.splice(newIndex, 0, key);
166
+
167
+ const previousSibling = this.metadata[newIndex - 1]?.domNode ?? this.anchorNode;
168
+ previousSibling.after(previousMetadata.domNode);
169
+ this.metadataCache.delete(key);
170
+ return;
171
+ }
172
+
173
+ // (Optimistic replace)
174
+ // Brand new key. Cache whatever is in current and replace
175
+ // If should have been insert, will correct itself next step.
176
+ // Allows multiple inserts to batch instead of one-by-one
177
+
178
+ // console.log('completely new key', 'removing old. will replace', newIndex);
179
+ this.metadataCache.set(metadataAtIndex.key, metadataAtIndex);
180
+
181
+ // Continue to PUT below
182
+ } else {
183
+ // Key is in the wrong spot (guaranteed to be oldIndex > newIndex)
184
+ // console.warn('Found key for', newIndex, '@', oldIndex);
185
+ // console.warn('swapping', newIndex, '<=>', oldIndex);
186
+ if ((newIndex - oldIndex) === -1) {
187
+ // (Optimistic removal)
188
+ // If element should be one step sooner, remove instead to shift up.
189
+ // If should have been swap, will correct itself next step.
190
+ // console.warn('Removing', newIndex, 'instead');
191
+ this.removeByIndex(newIndex);
192
+ return;
193
+ }
194
+ // Swap with other element
195
+ // Arrays should be iterated sequentially.
196
+ // Array can never swap before current index
197
+
198
+ // Store what's later in the tree to move here
199
+
200
+ const correctMetadata = this.metadata[oldIndex];
201
+
202
+ // Move back <=
203
+ this.metadata[newIndex] = correctMetadata;
204
+ this.metadata.splice(oldIndex, 1);
205
+
206
+ const { domNode: domNodeToRemove } = metadataAtIndex;
207
+ domNodeToRemove.replaceWith(correctMetadata.domNode);
208
+
209
+ if (!skipOnMatch) {
210
+ console.warn('no skip on match on swap', newIndex);
211
+ correctMetadata.render(changes, data);
212
+ }
213
+
214
+ // Remove posterior
215
+
216
+ this.keys[newIndex] = key;
217
+ this.keys.splice(oldIndex, 1);
218
+
219
+ domNodeToRemove.remove();
220
+
221
+ // Don't release in case we may need it later
222
+ // console.debug('Caching key', key);
223
+ this.metadataCache.set(metadataAtIndex.key, metadataAtIndex);
224
+
225
+ return;
226
+ }
227
+ }
228
+
229
+ const render = this.render(changes, data);
230
+ const element = render.target;
231
+
232
+ this.metadata[newIndex] = {
233
+ render,
234
+ element,
235
+ key,
236
+ domNode: element,
237
+ };
238
+ this.keys[newIndex] = key;
239
+
240
+ if (this.batchEndIndex === null || this.batchEndIndex !== (newIndex - 1)) {
241
+ this.writeBatch();
242
+ // Start new batch
243
+ this.batchStartIndex = newIndex;
244
+ }
245
+ this.batchEndIndex = newIndex;
246
+ this.queuedElements.push(element);
247
+ }
248
+
249
+ removeEntries(startIndex = 0) {
250
+ const { length } = this.metadata;
251
+ for (let index = length - 1; index >= startIndex; index--) {
252
+ this.metadata[index].domNode.remove();
253
+ }
254
+ this.metadata.length = startIndex;
255
+ this.keys.length = startIndex;
256
+ }
257
+
258
+ /**
259
+ * @param {number} [index]
260
+ * @param {ItemMetadata} [metadata]
261
+ * @param {any} [key]
262
+ * @return {boolean} changed
263
+ */
264
+ hide(index, metadata, key) {
265
+ if (!metadata) {
266
+ if (index == null) {
267
+ index = this.keys.indexOf(key);
268
+ }
269
+ metadata = this.metadata[index];
270
+ if (!metadata) {
271
+ return false;
272
+ }
273
+ }
274
+
275
+ if (metadata.hidden) return false;
276
+
277
+ let { comment, element } = metadata;
278
+ if (!comment) {
279
+ comment = createEmptyComment();
280
+ metadata.comment = comment;
281
+ }
282
+
283
+ element.replaceWith(comment);
284
+ metadata.domNode = comment;
285
+ metadata.hidden = true;
286
+ return true;
287
+ }
288
+
289
+ /**
290
+ * @param {number} [index]
291
+ * @param {ItemMetadata} [metadata]
292
+ * @param {any} [key]
293
+ * @return {boolean} changed
294
+ */
295
+ show(index, metadata, key) {
296
+ if (!metadata) {
297
+ if (index == null) {
298
+ index = this.keys.indexOf(key);
299
+ }
300
+ metadata = this.metadata[index];
301
+ if (!metadata) {
302
+ return false;
303
+ }
304
+ }
305
+
306
+ if (!metadata.hidden) return false;
307
+
308
+ const { comment, element } = metadata;
309
+
310
+ comment.replaceWith(element);
311
+ metadata.domNode = element;
312
+ metadata.hidden = false;
313
+ return true;
314
+ }
315
+ }