Skip to content
This repository was archived by the owner on Nov 30, 2020. It is now read-only.

Commit 42e9920

Browse files
authored
feat: add auto-init (#600)
1 parent 456728e commit 42e9920

File tree

8 files changed

+358
-0
lines changed

8 files changed

+358
-0
lines changed

Diff for: components/auto-init/AutoInit.vue

+158
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,158 @@
1+
<script>
2+
import autoInit from '@material/auto-init/index'
3+
import * as constants from '@material/auto-init/constants'
4+
5+
import * as checkbox from '@material/checkbox/index'
6+
import * as chips from '@material/chips/index'
7+
import * as dataTable from '@material/data-table/index'
8+
import * as dialog from '@material/dialog/index'
9+
import * as drawer from '@material/drawer/index'
10+
import * as floatingLabel from '@material/floating-label/index'
11+
import * as formField from '@material/form-field/index'
12+
import * as iconButton from '@material/icon-button/index'
13+
import * as lineRipple from '@material/line-ripple/index'
14+
import * as linearProgress from '@material/linear-progress/index'
15+
import * as list from '@material/list/index'
16+
import * as menuSurface from '@material/menu-surface/index'
17+
import * as menu from '@material/menu/index'
18+
import * as notchedOutline from '@material/notched-outline/index'
19+
import * as radio from '@material/radio/index'
20+
import * as ripple from '@material/ripple/index'
21+
import * as select from '@material/select/index'
22+
import * as slider from '@material/slider/index'
23+
import * as snackbar from '@material/snackbar/index'
24+
import * as switchControl from '@material/switch/index'
25+
import * as tabBar from '@material/tab-bar/index'
26+
import * as textField from '@material/textfield/index'
27+
import * as topAppBar from '@material/top-app-bar/index'
28+
29+
import MDCComponent from '@material/base/component'
30+
31+
// Register all components
32+
autoInit.register('MDCCheckbox', checkbox.MDCCheckbox)
33+
autoInit.register('MDCChip', chips.MDCChip)
34+
autoInit.register('MDCChipSet', chips.MDCChipSet)
35+
autoInit.register('MDCDataTable', dataTable.MDCDataTable)
36+
autoInit.register('MDCDialog', dialog.MDCDialog)
37+
autoInit.register('MDCDrawer', drawer.MDCDrawer)
38+
autoInit.register('MDCFloatingLabel', floatingLabel.MDCFloatingLabel)
39+
autoInit.register('MDCFormField', formField.MDCFormField)
40+
autoInit.register('MDCIconButtonToggle', iconButton.MDCIconButtonToggle)
41+
autoInit.register('MDCLineRipple', lineRipple.MDCLineRipple)
42+
autoInit.register('MDCLinearProgress', linearProgress.MDCLinearProgress)
43+
autoInit.register('MDCList', list.MDCList)
44+
autoInit.register('MDCMenu', menu.MDCMenu)
45+
autoInit.register('MDCMenuSurface', menuSurface.MDCMenuSurface)
46+
autoInit.register('MDCNotchedOutline', notchedOutline.MDCNotchedOutline)
47+
autoInit.register('MDCRadio', radio.MDCRadio)
48+
autoInit.register('MDCRipple', ripple.MDCRipple)
49+
autoInit.register('MDCSelect', select.MDCSelect)
50+
autoInit.register('MDCSlider', slider.MDCSlider)
51+
autoInit.register('MDCSnackbar', snackbar.MDCSnackbar)
52+
autoInit.register('MDCSwitch', switchControl.MDCSwitch)
53+
autoInit.register('MDCTabBar', tabBar.MDCTabBar)
54+
autoInit.register('MDCTextField', textField.MDCTextField)
55+
autoInit.register('MDCTopAppBar', topAppBar.MDCTopAppBar)
56+
57+
const constructors = {
58+
MDCCheckbox: checkbox.MDCCheckbox,
59+
MDCChip: chips.MDCChip,
60+
MDCChipSet: chips.MDCChipSet,
61+
MDCDataTable: dataTable.MDCDataTable,
62+
MDCDialog: dialog.MDCDialog,
63+
MDCDrawer: drawer.MDCDrawer,
64+
MDCFloatingLabel: floatingLabel.MDCFloatingLabel,
65+
MDCFormField: formField.MDCFormField,
66+
MDCIconButtonToggle: iconButton.MDCIconButtonToggle,
67+
MDCLineRipple: lineRipple.MDCLineRipple,
68+
MDCLinearProgress: linearProgress.MDCLinearProgress,
69+
MDCList: list.MDCList,
70+
MDCMenu: menu.MDCMenu,
71+
MDCMenuSurface: menuSurface.MDCMenuSurface,
72+
MDCNotchedOutline: notchedOutline.MDCNotchedOutline,
73+
MDCRadio: radio.MDCRadio,
74+
MDCRipple: ripple.MDCRipple,
75+
MDCSelect: select.MDCSelect,
76+
MDCSlider: slider.MDCSlider,
77+
MDCSnackbar: snackbar.MDCSnackbar,
78+
MDCSwitch: switchControl.MDCSwitch,
79+
MDCTabBar: tabBar.MDCTabBar,
80+
MDCTextField: textField.MDCTextField,
81+
MDCTopAppBar: topAppBar.MDCTopAppBar
82+
}
83+
84+
export default {
85+
inheritAttrs: false,
86+
data: function () {
87+
return {
88+
component: undefined
89+
}
90+
},
91+
mounted () {
92+
this.$nextTick(function () {
93+
this.init()
94+
})
95+
},
96+
updated () {
97+
this.$nextTick(function () {
98+
this.init()
99+
})
100+
},
101+
methods: {
102+
init () {
103+
const node = this.$el
104+
if (this.component instanceof MDCComponent && this.component.root_ !== this.$el) {
105+
this.destroy()
106+
}
107+
if (
108+
this.component == null &&
109+
node instanceof HTMLElement &&
110+
node.hasAttribute(constants.strings.AUTO_INIT_ATTR) &&
111+
node.getAttribute(constants.strings.AUTO_INIT_STATE_ATTR) !== constants.strings.INITIALIZED_STATE) {
112+
// following codes are copied from https://github.com/material-components/material-components-web/blob/master/packages/mdc-auto-init/index.ts
113+
const ctorName = node.getAttribute(constants.strings.AUTO_INIT_ATTR)
114+
if (!ctorName) {
115+
throw new Error('(mdc-auto-init) Constructor name must be given.')
116+
}
117+
118+
const Constructor = constructors[ctorName]
119+
if (typeof Constructor !== 'function') {
120+
throw new Error(
121+
`(mdc-auto-init) Could not find constructor in registry for ${ctorName}`)
122+
}
123+
124+
const component = Constructor.attachTo(node)
125+
Object.defineProperty(node, ctorName, {
126+
configurable: true,
127+
enumerable: false,
128+
value: component,
129+
writable: false
130+
})
131+
132+
this.component = component
133+
node.setAttribute(constants.strings.AUTO_INIT_STATE_ATTR, constants.strings.INITIALIZED_STATE)
134+
this.$emit('end', this.component)
135+
}
136+
},
137+
destroy () {
138+
if (this.component instanceof MDCComponent) {
139+
this.component.destroy()
140+
this.component = undefined
141+
}
142+
}
143+
},
144+
render: function (h) {
145+
const scopedSlot =
146+
this.$scopedSlots.default &&
147+
this.$scopedSlots.default({
148+
component: this.components
149+
})
150+
if (scopedSlot && scopedSlot.length > 0) {
151+
return scopedSlot[0]
152+
} else {
153+
this.destroy()
154+
return h()
155+
}
156+
}
157+
}
158+
</script>

Diff for: components/auto-init/README.md

+54
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
## Auto Init
2+
3+
### Markup
4+
5+
```html
6+
<m-auto-init @end="textField = $event" ref="component">
7+
<label class="mdc-text-field" data-mdc-auto-init="MDCTextField">
8+
<span class="mdc-text-field__ripple"></span>
9+
<input class="mdc-text-field__input" type="text" aria-labelledby="label">
10+
<span id="label" class="mdc-floating-label">Input Label</span>
11+
<span class="mdc-line-ripple"></span>
12+
</label>
13+
</m-auto-init>
14+
```
15+
16+
### Script
17+
18+
```javascript
19+
data () {
20+
return {
21+
textField: undefined // after initialization, it will be an MDCTextField instance
22+
}
23+
}
24+
```
25+
26+
### Re-Initialize
27+
28+
```javascript
29+
this.$refs.component.destroy()
30+
this.$refs.component.$el.removeAttribute('data-mdc-auto-init-state')
31+
```
32+
33+
### Events
34+
35+
| Event | Payload | Description |
36+
|-------|---------|-------------|
37+
| end | `MDCComponent` | emitted when the component being initialized |
38+
39+
### Methods
40+
41+
| Method | Description |
42+
|-------|-------------|
43+
| destroy | calling `MDCComponent.destroy`, useful in re-initialization |
44+
45+
### Slots
46+
47+
| Slot | Description |
48+
|------|-------------|
49+
| default | a material component dom. **Can only contain one element** |
50+
51+
52+
### Reference
53+
54+
- https://github.com/material-components/material-components-web/tree/master/packages/mdc-auto-init

Diff for: components/auto-init/index.js

+12
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
import AutoInit from './AutoInit.vue'
2+
3+
import { initPlugin } from '../'
4+
5+
const plugin = {
6+
install (vm) {
7+
vm.component('m-auto-init', AutoInit)
8+
}
9+
}
10+
export default plugin
11+
12+
initPlugin(plugin)

Diff for: docs/.vuepress/components/DataTableDemo.vue

+125
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,125 @@
1+
<template>
2+
<div>
3+
<ComponentSection>
4+
<m-auto-init>
5+
<div class="mdc-data-table" data-mdc-auto-init="MDCDataTable">
6+
<table class="mdc-data-table__table" aria-label="Dessert calories">
7+
<thead>
8+
<tr class="mdc-data-table__header-row">
9+
<th class="mdc-data-table__header-cell mdc-data-table__header-cell--checkbox" role="columnheader" scope="col">
10+
<div class="mdc-checkbox mdc-data-table__header-row-checkbox mdc-checkbox--selected">
11+
<input type="checkbox" class="mdc-checkbox__native-control" aria-label="Checkbox for header row selection"/>
12+
<div class="mdc-checkbox__background">
13+
<svg class="mdc-checkbox__checkmark" viewbox="0 0 24 24">
14+
<path class="mdc-checkbox__checkmark-path" fill="none" d="M1.73,12.91 8.1,19.28 22.79,4.59" />
15+
</svg>
16+
<div class="mdc-checkbox__mixedmark"></div>
17+
</div>
18+
</div>
19+
</th>
20+
<th class="mdc-data-table__header-cell" role="columnheader" scope="col">Status</th>
21+
<th class="mdc-data-table__header-cell" role="columnheader" scope="col">Signal name</th>
22+
<th class="mdc-data-table__header-cell" role="columnheader" scope="col">Severity</th>
23+
<th class="mdc-data-table__header-cell" role="columnheader" scope="col">Stage</th>
24+
<th class="mdc-data-table__header-cell mdc-data-table__header-cell--numeric" role="columnheader" scope="col">Time</th>
25+
<th class="mdc-data-table__header-cell" role="columnheader" scope="col">Roles</th>
26+
</tr>
27+
</thead>
28+
<tbody class="mdc-data-table__content">
29+
<tr data-row-id="u0" class="mdc-data-table__row">
30+
<td class="mdc-data-table__cell mdc-data-table__cell--checkbox">
31+
<div class="mdc-checkbox mdc-data-table__row-checkbox">
32+
<input type="checkbox" class="mdc-checkbox__native-control" aria-labelledby="u0"/>
33+
<div class="mdc-checkbox__background">
34+
<svg class="mdc-checkbox__checkmark" viewbox="0 0 24 24">
35+
<path class="mdc-checkbox__checkmark-path" fill="none" d="M1.73,12.91 8.1,19.28 22.79,4.59" />
36+
</svg>
37+
<div class="mdc-checkbox__mixedmark"></div>
38+
</div>
39+
</div>
40+
</td>
41+
<td class="mdc-data-table__cell">Online</td>
42+
<td class="mdc-data-table__cell" id="u0">Arcus watch slowdown</td>
43+
<td class="mdc-data-table__cell">Medium</td>
44+
<td class="mdc-data-table__cell">Triaged</td>
45+
<td class="mdc-data-table__cell mdc-data-table__cell--numeric">0:33</td>
46+
<td class="mdc-data-table__cell">Allison Brie</td>
47+
</tr>
48+
<tr data-row-id="u1" class="mdc-data-table__row mdc-data-table__row--selected" aria-selected="true">
49+
<td class="mdc-data-table__cell mdc-data-table__cell--checkbox">
50+
<div class="mdc-checkbox mdc-data-table__row-checkbox mdc-checkbox--selected">
51+
<input type="checkbox" class="mdc-checkbox__native-control" checked aria-labelledby="u1"/>
52+
<div class="mdc-checkbox__background">
53+
<svg class="mdc-checkbox__checkmark" viewbox="0 0 24 24">
54+
<path class="mdc-checkbox__checkmark-path" fill="none" d="M1.73,12.91 8.1,19.28 22.79,4.59" />
55+
</svg>
56+
<div class="mdc-checkbox__mixedmark"></div>
57+
</div>
58+
</div>
59+
</td>
60+
<td class="mdc-data-table__cell">Offline</td>
61+
<td class="mdc-data-table__cell" id="u1">monarch: prod shared ares-managed-features-provider-heavy</td>
62+
<td class="mdc-data-table__cell">Huge</td>
63+
<td class="mdc-data-table__cell">Triaged</td>
64+
<td class="mdc-data-table__cell mdc-data-table__cell--numeric">0:33</td>
65+
<td class="mdc-data-table__cell">Brie Larson</td>
66+
</tr>
67+
<tr data-row-id="u2" class="mdc-data-table__row mdc-data-table__row--selected" aria-selected="true">
68+
<td class="mdc-data-table__cell mdc-data-table__cell--checkbox">
69+
<div class="mdc-checkbox mdc-data-table__row-checkbox mdc-checkbox--selected">
70+
<input type="checkbox" class="mdc-checkbox__native-control" checked aria-labelledby="u2"/>
71+
<div class="mdc-checkbox__background">
72+
<svg class="mdc-checkbox__checkmark" viewbox="0 0 24 24">
73+
<path class="mdc-checkbox__checkmark-path" fill="none" d="M1.73,12.91 8.1,19.28 22.79,4.59" />
74+
</svg>
75+
<div class="mdc-checkbox__mixedmark"></div>
76+
</div>
77+
</div>
78+
</td>
79+
<td class="mdc-data-table__cell">Online</td>
80+
<td class="mdc-data-table__cell" id="u2">monarch: prod shared ares-managed-features-provider-heavy</td>
81+
<td class="mdc-data-table__cell">Minor</td>
82+
<td class="mdc-data-table__cell">Not triaged</td>
83+
<td class="mdc-data-table__cell mdc-data-table__cell--numeric">0:33</td>
84+
<td class="mdc-data-table__cell">Jeremy Lake</td>
85+
</tr>
86+
<tr data-row-id="u3" class="mdc-data-table__row">
87+
<td class="mdc-data-table__cell mdc-data-table__cell--checkbox">
88+
<div class="mdc-checkbox mdc-data-table__row-checkbox">
89+
<input type="checkbox" class="mdc-checkbox__native-control" aria-labelledby="u3"/>
90+
<div class="mdc-checkbox__background">
91+
<svg class="mdc-checkbox__checkmark" viewbox="0 0 24 24">
92+
<path class="mdc-checkbox__checkmark-path" fill="none" d="M1.73,12.91 8.1,19.28 22.79,4.59" />
93+
</svg>
94+
<div class="mdc-checkbox__mixedmark"></div>
95+
</div>
96+
</div>
97+
</td>
98+
<td class="mdc-data-table__cell">Online</td>
99+
<td class="mdc-data-table__cell" id="u3">Arcus watch slowdown</td>
100+
<td class="mdc-data-table__cell">Negligible</td>
101+
<td class="mdc-data-table__cell">Triaged</td>
102+
<td class="mdc-data-table__cell mdc-data-table__cell--numeric">0:33</td>
103+
<td class="mdc-data-table__cell">Angelina Cheng</td>
104+
</tr>
105+
</tbody>
106+
</table>
107+
</div>
108+
</m-auto-init>
109+
</ComponentSection>
110+
<ComponentProps
111+
:radioProps="radioProps"
112+
:checkboxProps="checkboxProps"/>
113+
</div>
114+
</template>
115+
116+
<script>
117+
export default {
118+
data () {
119+
return {
120+
radioProps: [],
121+
checkboxProps: []
122+
}
123+
}
124+
}
125+
</script>

Diff for: docs/.vuepress/enhanceApp.js

+2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import './styles.scss'
22

3+
import AutoInit from '../../components/auto-init'
34
import Button from '../../components/button'
45
import Icon from '../../components/icon'
56
import Radio from '../../components/radio'
@@ -36,6 +37,7 @@ export default ({
3637
router, // the router instance for the app
3738
siteData // site metadata
3839
}) => {
40+
Vue.use(AutoInit)
3941
Vue.use(Button)
4042
Vue.use(Icon)
4143
Vue.use(Radio)

Diff for: docs/.vuepress/styles.scss

+2
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@ $fa-font-path: "~@fortawesome/fontawesome-free/webfonts";
66
@import "~@fortawesome/fontawesome-free/scss/solid";
77
@import "~@fortawesome/fontawesome-free/scss/regular";
88

9+
@import "@material/data-table/mdc-data-table";
10+
911
@import "../../components/theme/styles";
1012
@import "../../components/typography/styles";
1113
@import "../../components/layout-grid/styles";

Diff for: docs/components/README.md

+4
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,10 @@ The demonstration in this page is a work in progress..
5656

5757
<MenuSurfaceDemo/>
5858

59+
## Data Table (using Auto Init)
60+
61+
<DataTableDemo/>
62+
5963
## Dialog
6064

6165
<DialogDemo/>

Diff for: webpack.config.common.js

+1
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ const nodeModules = path.join(root, '/node_modules/')
99

1010
module.exports = {
1111
entry: {
12+
'auto-init': path.resolve(components + '/auto-init/index.js'),
1213
button: path.resolve(components + '/button/index.js'),
1314
card: path.resolve(components + '/card/index.js'),
1415
checkbox: path.resolve(components + '/checkbox/index.js'),

0 commit comments

Comments
 (0)