@skeletonizer/vue 0.0.23-alpha.0 → 1.1.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.
- package/README.md +73 -197
- package/package.json +21 -19
- package/dist/components/SkeletonizerSkeleton.vue.d.ts +0 -78
- package/dist/index.css +0 -1
- package/dist/index.d.ts +0 -4
- package/dist/skeletonizer-vue.mjs +0 -53
- package/dist/skeletonizer-vue.umd.js +0 -2
package/README.md
CHANGED
|
@@ -8,12 +8,13 @@ To install the package, run the following command:
|
|
|
8
8
|
`@skeletonizer/vue` is always used in conjunction with `@skeletonizer/utils`. The `@skeletonizer/utils` package provides the core functionality for creating skeletonized views, while the `@skeletonizer/vue` package provides the Vue-specific functionality. **The versions should always match**.
|
|
9
9
|
|
|
10
10
|
## main.ts
|
|
11
|
-
In your `main.ts` file (where you do `createApp`), you need to install the `SkeletonizerPlugin
|
|
11
|
+
In your `main.ts` file (where you do `createApp`), you need to install the `SkeletonizerPlugin` and import the css needed for the plugin. The plugin provides the `SkeletonizerSkeleton` component and directive that will be used in your Vue components.
|
|
12
12
|
|
|
13
13
|
```typescript
|
|
14
14
|
import { createApp } from 'vue';
|
|
15
15
|
import App from './App.vue';
|
|
16
16
|
import { SkeletonizerPlugin } from '@skeletonizer/vue';
|
|
17
|
+
import '@skeletonizer/vue/dist/index.css';
|
|
17
18
|
|
|
18
19
|
createApp(App)
|
|
19
20
|
.use(SkeletonizerPlugin)
|
|
@@ -21,20 +22,32 @@ createApp(App)
|
|
|
21
22
|
```
|
|
22
23
|
|
|
23
24
|
## Component Adjustments
|
|
24
|
-
Generally speaking, all you need to do to use the skeletonizer in the template, is to wrap the part of the template you wish to skeletonize in the `<skeletonizer-skeleton>` component.
|
|
25
|
-
|
|
25
|
+
Generally speaking, all you need to do to use the skeletonizer in the template, is to wrap the part of the template you wish to skeletonize in the `<skeletonizer-skeleton>` component. Additionally, you will need to pass the following to `skeletonizer-skeleton`:
|
|
26
|
+
- `v-slot="{ scope }"`
|
|
27
|
+
- `:config="skeletonizer.skeletonConfig"`
|
|
28
|
+
- `:show-skeleton="skeletonizer.showSkeleton"`
|
|
29
|
+
- `:scope="{ foo, bar }"`
|
|
30
|
+
|
|
31
|
+
All the data that you wish to access in the skeletonized part of the template must be provided in the `:scope` and accessed through the `skeletonizer.proxy(scope)` method, except the data that you provide and is available even whilst the data is being loaded (ie. `:show-skeleton="true"`). For example, if you have a `message` prop that you wish to be skeletonized, you'll need to pass it to the `:scope` object and access it through the `skeletonizer.proxy(scope).message` method.
|
|
26
32
|
|
|
27
33
|
As far as the template goes, it essentially means transforming the code from this:
|
|
28
34
|
```html
|
|
29
35
|
<div>{{ somePropOrMethodCallAvailableAsync }}</div>
|
|
36
|
+
<div>{{ otherAsyncProp }}</div>
|
|
30
37
|
<div>{{ someAlreadyHardCodedOrInputBoundPropAvailableSync }} </div>
|
|
31
38
|
```
|
|
32
39
|
|
|
33
40
|
into this:
|
|
34
41
|
|
|
35
42
|
```html
|
|
36
|
-
<skeletonizer-skeleton
|
|
37
|
-
|
|
43
|
+
<skeletonizer-skeleton
|
|
44
|
+
v-slot="{ scope }"
|
|
45
|
+
:config="skeletonizer.skeletonConfig"
|
|
46
|
+
:show-skeleton="skeletonizer.showSkeleton"
|
|
47
|
+
:scope="{ somePropOrMethodCallAvailableAsync, otherAsyncProp }"
|
|
48
|
+
>
|
|
49
|
+
<div>{{ skeletonizer.proxy(scope).somePropOrMethodCallAvailableAsync }}</div>
|
|
50
|
+
<div>{{ skeletonizer.proxy(scope).otherAsyncProp }}</div>
|
|
38
51
|
<div>{{ someAlreadyHardCodedOrInputBoundPropAvailableSync }} </div>
|
|
39
52
|
</skeletonizer-skeleton>
|
|
40
53
|
```
|
|
@@ -42,20 +55,14 @@ into this:
|
|
|
42
55
|
As long as the shape of the properties you access within the skeleton part of the template matches the shape of the data you provide in the `scope` and `skeletonConfig` properties, the skeletonized view will be in sync with the actual view, regardless of changes to the design.
|
|
43
56
|
|
|
44
57
|
## Usage
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
If you wish to use Skeletonizer in a standalone component, you need to add `SkeletonizerSkeletonComponent` in the imports of the component.
|
|
48
|
-
The usage in a component that is a part of a module is the same as the standalone component, but you need to add `SkeletonizerSkeletonComponent` in the imports of the **module** where the component is declared.
|
|
49
|
-
|
|
50
|
-
Every component that uses Skeletonizer should extend `SkeletonAbstractComponent`, which is available in `@skeletonizer/utils`.
|
|
51
|
-
The `SkeletonAbstractComponent` requires you to pass a type argument that represents the data model of the **part(s) of the component that you intend to skeletonize**.
|
|
52
|
-
It also requires you to implement the `skeletonConfig` (type validated against the type argument you pass to `SkeletonAbstractComponent`) and `showSkeleton` properties which must be passed to the `SkeletonizerSkeletonComponent` as inputs.
|
|
53
|
-
By extending the `SkeletonAbstractComponent`, you also get access to the `proxy` method via which you can (type) safely access props and methods **within the skeletonized part of the current component**.
|
|
58
|
+
Every component that uses Skeletonizer should use `SkeletonizerComponentComposable`, which is available in `@skeletonizer/vue`. Both the component and the `SkeletonizerComponentComposable` are type-safe - if the shape of `schemaGenerator` returned object does not match the shape of type generic you pass to `SkeletonizerComponentComposable`, you will get a type error. You will also get an error if you fail to pass the same shape to the `:scope` input bound property of `skeletonizer-skeleton` component. While Vue has made noticeable strides in type safety, it is still lacking a bit compared to eg. Angular. Therefor, you may still need to run a `npm run type-check` command (which, in a standard vue/vite project, executes `vue-tsc --noEmit -p tsconfig.vitest.json --composite false`) if you wish to get the extra type safety.
|
|
54
59
|
|
|
55
|
-
|
|
56
|
-
|
|
60
|
+
You can use multiple separate, independently skeletonized parts within the same component. In that case, you can:
|
|
61
|
+
- provide separate `:scope`, `:show-skeleton` and `:config` properties for each `skeletonizer-skeleton` component. For easier maintenance, it is still recommended that you prefix (or suffix) all of the referenced composables with `skeletonizer` (eg. `profileSkeletonizer`, or `skeletonizerUsersList`) to make it clear that they are part of the skeletonized view. In that case, you should obviously access each `.proxy` method with the corresponding composables (eg. `profileSkeletonizer.proxy(scope)`).
|
|
62
|
+
- provide the same `:scope` and `:config` property to all `skeletonizer-skeleton` components, with separate `:show-skeleton` properties for each `skeletonizer-skeleton` component.
|
|
57
63
|
|
|
58
|
-
|
|
64
|
+
In the skeletonized part of the template, you **must** access the data through the `skeletonizerFoo.proxy(scope)` method.
|
|
65
|
+
You can think of `skeletonizerFoo.proxy(scope)` in the same way as you would think of `this` in a class method. The only difference is that when using `skeletonizerFoo.proxy(scope)`, the content-projected template will use the mocked values when the `showSkeleton` is `true`, and resolved values when `showSkeleton` is `false` - all while maintaining the type safety.
|
|
59
66
|
|
|
60
67
|
For more details about the `SchemaItem` property, see the [SchemaItem](/packages/utils/README.md#schemaitem) section.
|
|
61
68
|
|
|
@@ -63,10 +70,11 @@ For more details about the `skeletonConfig` property, see the [TSchemaConfig](/p
|
|
|
63
70
|
|
|
64
71
|
|
|
65
72
|
```typescript
|
|
66
|
-
|
|
67
|
-
import {
|
|
68
|
-
import { SchemaItem
|
|
69
|
-
import {
|
|
73
|
+
// <script setup lang="ts">
|
|
74
|
+
import { SkeletonizerComponentComposable, SkeletonizerSkeleton } from '@skeletonizer/vue';
|
|
75
|
+
import { SchemaItem } from '@skeletonizer/utils';
|
|
76
|
+
import { type Ref, ref } from 'vue';
|
|
77
|
+
import assetImgUrl from '@/assets/logo.svg';
|
|
70
78
|
|
|
71
79
|
interface IResource {
|
|
72
80
|
title: string;
|
|
@@ -75,200 +83,68 @@ interface IResource {
|
|
|
75
83
|
}
|
|
76
84
|
|
|
77
85
|
// the svgs are just for the sake of the example
|
|
78
|
-
const
|
|
79
|
-
|
|
80
|
-
|
|
86
|
+
const supportSvg: string = `
|
|
87
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" fill="currentColor">
|
|
88
|
+
<path
|
|
89
|
+
d="M10 3.22l-.61-.6a5.5 5.5 0 0 0-7.666.105 5.5 5.5 0 0 0-.114 7.665L10 18.78l8.39-8.4a5.5 5.5 0 0 0-.114-7.665 5.5 5.5 0 0 0-7.666-.105l-.61.61z"
|
|
90
|
+
/>
|
|
91
|
+
</svg>
|
|
92
|
+
`;
|
|
81
93
|
|
|
82
94
|
const loadingSvg: string = '<svg width="24" height="24" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><style>.spinner{transform-origin:center;animation:spinner .75s linear infinite}@keyframes spinner{from{transform:rotate(0deg)}to{transform:rotate(360deg)}}</style><g class="spinner"><circle cx="12" cy="2.5" r="1.5" opacity=".14"/><circle cx="16.75" cy="3.77" r="1.5" opacity=".29"/><circle cx="20.23" cy="7.25" r="1.5" opacity=".43"/><circle cx="21.50" cy="12.00" r="1.5" opacity=".57"/><circle cx="20.23" cy="16.75" r="1.5" opacity=".71"/><circle cx="16.75" cy="20.23" r="1.5" opacity=".86"/><circle cx="12" cy="21.5" r="1.5"/></g></svg>';
|
|
83
95
|
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
<a *ngFor="let resource of proxy(context).resources" target="_blank" rel="noopener" [href]="resource.link">
|
|
96
|
-
<div [innerHTML]="sanitizer.bypassSecurityTrustHtml(resource.svg)"></div>
|
|
97
|
-
<span>{{ resource.title }}</span>
|
|
98
|
-
</a>
|
|
99
|
-
</ng-template>
|
|
100
|
-
</skeletonizer-skeleton>
|
|
101
|
-
`,
|
|
102
|
-
styleUrls: ['./my-component.component.scss'],
|
|
103
|
-
// for standalone components, otherwise add SkeletonizerSkeletonComponent to the module imports of the module where MyComponent is declared
|
|
104
|
-
// standalone: true,
|
|
105
|
-
// imports: [SkeletonizerSkeletonComponent, NgFor], // ngFor is just for the sake of the example where the *ngFor is used in the template
|
|
106
|
-
})
|
|
107
|
-
export class MyComponent extends SkeletonAbstractComponent<TSkeletonizedPart> implements OnInit {
|
|
108
|
-
public pageTitle: string = 'Some prop that we do not wish to skeletonize, but wish to use in the view nonetheless';
|
|
109
|
-
public otherPropWeWantToUseInSkeletonizedPart: string = 'angular';
|
|
110
|
-
|
|
111
|
-
public resources: IResource[] = [];
|
|
112
|
-
public showSkeleton: boolean = true;
|
|
113
|
-
|
|
114
|
-
public readonly skeletonConfig: TSchemaConfig<TSkeletonizedPart> = {
|
|
115
|
-
repeat: 1,
|
|
96
|
+
const pageTitle: string = 'Some prop that we do not wish to skeletonize, but wish to use in the view nonetheless';
|
|
97
|
+
const message: Ref<string> = ref('vue');
|
|
98
|
+
const resources: Ref<IResource[]> = ref([]);
|
|
99
|
+
|
|
100
|
+
type TSkeletonized = { message: string, resources: IResource[] };
|
|
101
|
+
|
|
102
|
+
// if you call this const eg. `skeletonizerFoo`, you should access the skeletonized props in the template with `skeletonizerFoo.proxy(scope).someProp`
|
|
103
|
+
// if you need multiple separate skeletonized parts, you should create multiple separate composables using `SkeletonizerComponentComposable.generate` and provide separate `:scope`, `:show-skeleton` and `:config` properties for each `skeletonizer-skeleton` component.
|
|
104
|
+
const skeletonizer: SkeletonizerComponentComposable<TSkeletonized> = SkeletonizerComponentComposable.generate<TSkeletonized>(
|
|
105
|
+
{
|
|
106
|
+
repeat: 3,
|
|
116
107
|
schemaGenerator: () => ({
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
link: new SchemaItem().identical('https://www.google.com'),
|
|
108
|
+
message: new SchemaItem().words(5),
|
|
109
|
+
resources: Array.from({ length: 3 }, () => ({
|
|
110
|
+
title: new SchemaItem().words(2),
|
|
111
|
+
link: new SchemaItem().identical('https://vuejs.org/'),
|
|
122
112
|
svg: new SchemaItem().identical(loadingSvg),
|
|
123
|
-
}))
|
|
113
|
+
}))
|
|
124
114
|
}),
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
public readonly sanitizer: DomSanitizer,
|
|
129
|
-
) {
|
|
130
|
-
super();
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
public ngOnInit(): void {
|
|
134
|
-
// simulate loading data
|
|
135
|
-
setTimeout(() => {
|
|
136
|
-
this.resources = [
|
|
137
|
-
{
|
|
138
|
-
title: 'Mocked Resolved Resource #1',
|
|
139
|
-
link: 'https://github.com/lukaVarga/skeletonizer/tree/main/packages/angular/projects/skeletonizer',
|
|
140
|
-
svg: learnNgSvg,
|
|
141
|
-
},
|
|
142
|
-
{
|
|
143
|
-
title: 'Mocked Resolved Resource #2',
|
|
144
|
-
link: 'https://github.com/lukaVarga/skeletonizer/tree/main',
|
|
145
|
-
svg: cliDocsSvg,
|
|
146
|
-
},
|
|
147
|
-
];
|
|
148
|
-
|
|
149
|
-
this.otherPropWeWantToUseInSkeletonizedPart = 'loaded title'
|
|
150
|
-
|
|
151
|
-
this.showSkeleton = false;
|
|
152
|
-
}, Math.max(3_000, Math.random() * 10_000));
|
|
153
|
-
}
|
|
154
|
-
}
|
|
155
|
-
```
|
|
115
|
+
},
|
|
116
|
+
true,
|
|
117
|
+
);
|
|
156
118
|
|
|
157
|
-
|
|
158
|
-
|
|
119
|
+
setTimeout(() => {
|
|
120
|
+
message.value = 'Async update of message';
|
|
159
121
|
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
import { DomSanitizer } from '@angular/platform-browser';
|
|
122
|
+
resources.value = [
|
|
123
|
+
{ title: 'Vue', link: 'https://vuejs.org/', svg: assetImgUrl },
|
|
124
|
+
{ title: 'Vite', link: 'https://vitejs.dev/', svg: supportSvg },
|
|
125
|
+
];
|
|
165
126
|
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
link: string;
|
|
169
|
-
svg: string;
|
|
170
|
-
}
|
|
171
|
-
|
|
172
|
-
// the svgs are just for the sake of the example
|
|
173
|
-
const learnNgSvg: string = '<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><path d="M5 13.18v4L12 21l7-3.82v-4L12 17l-7-3.82zM12 3L1 9l11 6 9-4.91V17h2V9L12 3z"/></svg>';
|
|
174
|
-
|
|
175
|
-
const loadingSvg: string = '<svg width="24" height="24" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><style>.spinner{transform-origin:center;animation:spinner .75s linear infinite}@keyframes spinner{from{transform:rotate(0deg)}to{transform:rotate(360deg)}}</style><g class="spinner"><circle cx="12" cy="2.5" r="1.5" opacity=".14"/><circle cx="16.75" cy="3.77" r="1.5" opacity=".29"/><circle cx="20.23" cy="7.25" r="1.5" opacity=".43"/><circle cx="21.50" cy="12.00" r="1.5" opacity=".57"/><circle cx="20.23" cy="16.75" r="1.5" opacity=".71"/><circle cx="16.75" cy="20.23" r="1.5" opacity=".86"/><circle cx="12" cy="21.5" r="1.5"/></g></svg>';
|
|
127
|
+
skeletonizer.showSkeleton = false;
|
|
128
|
+
}, 5000 * Math.random());
|
|
176
129
|
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
@Component({
|
|
180
|
-
selector: 'my-component',
|
|
181
|
-
template: `
|
|
182
|
-
<h2>{{ pageTitle }}</h2>
|
|
183
|
-
|
|
184
|
-
<skeletonizer-skeleton [showSkeleton]="showSkeleton" [config]="skeletonConfig" [scope]="{ resources, otherPropWeWantToUseInSkeletonizedPart }">
|
|
185
|
-
<ng-template let-context>
|
|
186
|
-
<div class="card-container">
|
|
187
|
-
<a *ngFor="let resource of proxy(context).resources" class="card" target="_blank" rel="noopener" [href]="resource.link">
|
|
188
|
-
<div [innerHTML]="sanitizer.bypassSecurityTrustHtml(resource.svg)"></div>
|
|
189
|
-
<span>{{ resource.title }}</span>
|
|
190
|
-
</a>
|
|
191
|
-
</div>
|
|
192
|
-
</ng-template>
|
|
193
|
-
</skeletonizer-skeleton>
|
|
194
|
-
|
|
195
|
-
<skeletonizer-skeleton [showSkeleton]="showOtherSkeleton" [config]="skeletonConfig" [scope]="{ resources, otherPropWeWantToUseInSkeletonizedPart }">
|
|
196
|
-
<ng-template let-context>
|
|
197
|
-
<span>{{ proxy(context).otherPropWeWantToUseInSkeletonizedPart }}</span>
|
|
198
|
-
</ng-template>
|
|
199
|
-
</skeletonizer-skeleton>
|
|
200
|
-
`,
|
|
201
|
-
styleUrls: ['./my-component.component.scss'],
|
|
202
|
-
// for standalone components, otherwise add SkeletonizerSkeletonComponent to the module imports of the module where MyComponent is declared
|
|
203
|
-
// standalone: true,
|
|
204
|
-
// imports: [SkeletonizerSkeletonComponent, NgFor], // ngFor is just for the sake of the example where the *ngFor is used in the template
|
|
205
|
-
})
|
|
206
|
-
export class MyComponent extends SkeletonAbstractComponent<TSkeletonizedPart> implements OnInit {
|
|
207
|
-
public pageTitle: string = 'Some prop that we do not wish to skeletonize, but wish to use in the view nonetheless';
|
|
208
|
-
public otherPropWeWantToUseInSkeletonizedPart: string = 'angular';
|
|
209
|
-
|
|
210
|
-
public resources: IResource[] = [];
|
|
211
|
-
public showSkeleton: boolean = true;
|
|
212
|
-
|
|
213
|
-
public readonly skeletonConfig: TSchemaConfig<TSkeletonizedPart> = {
|
|
214
|
-
repeat: 1,
|
|
215
|
-
schemaGenerator: () => ({
|
|
216
|
-
otherPropWeWantToUseInSkeletonizedPart: new SchemaItem<string>().words(3),
|
|
217
|
-
// Array.from({ length: 5 }, () => ({ ... })) is just a simple way of creating an array of 5 objects - you could also hardcode the array if you wanted to
|
|
218
|
-
resources: Array.from({ length: 5 }, () => ({
|
|
219
|
-
title: new SchemaItem<string>().words(3),
|
|
220
|
-
link: new SchemaItem().identical('https://www.google.com'),
|
|
221
|
-
svg: new SchemaItem().identical(loadingSvg),
|
|
222
|
-
})),
|
|
223
|
-
}),
|
|
224
|
-
};
|
|
225
|
-
|
|
226
|
-
public constructor(
|
|
227
|
-
public readonly sanitizer: DomSanitizer,
|
|
228
|
-
) {
|
|
229
|
-
super();
|
|
230
|
-
}
|
|
231
|
-
|
|
232
|
-
public ngOnInit(): void {
|
|
233
|
-
setTimeout(() => {
|
|
234
|
-
this.resources = [
|
|
235
|
-
{
|
|
236
|
-
title: 'Mocked Resolved Resource #1',
|
|
237
|
-
link: 'https://github.com/lukaVarga/skeletonizer/tree/main/packages/angular/projects/skeletonizer',
|
|
238
|
-
svg: learnNgSvg,
|
|
239
|
-
},
|
|
240
|
-
{
|
|
241
|
-
title: 'Mocked Resolved Resource #2',
|
|
242
|
-
link: 'https://github.com/lukaVarga/skeletonizer/tree/main',
|
|
243
|
-
svg: cliDocsSvg,
|
|
244
|
-
},
|
|
245
|
-
];
|
|
246
|
-
|
|
247
|
-
this.showSkeleton = false;
|
|
248
|
-
}, Math.max(3_000, Math.random() * 10_000));
|
|
249
|
-
|
|
250
|
-
setTimeout(() => {
|
|
251
|
-
this.showOtherSkeleton = false;
|
|
252
|
-
}, Math.max(6_000, Math.random() * 10_000));
|
|
253
|
-
}
|
|
254
|
-
}
|
|
130
|
+
// </script>
|
|
255
131
|
```
|
|
256
132
|
|
|
257
133
|
### Color Scheme
|
|
258
|
-
Generally speaking, you shouldn't need to adjust the color scheme of the skeletonized component in most cases. However, should you need to, the color scheme of the skeletonized views can be customized by providing the `
|
|
134
|
+
Generally speaking, you shouldn't need to adjust the color scheme of the skeletonized component in most cases. However, should you need to, the color scheme of the skeletonized views can be customized by providing the `:color-schema` property to the `<skeletonizer-skeleton>`.
|
|
135
|
+
|
|
136
|
+
For more details about the `:color-schema` property, see the [colorSchema](/packages/utils/README.md#colorschema) section.
|
|
259
137
|
|
|
260
|
-
For more details about the `colorScheme` property, see the [colorScheme](/packages/utils/README.md#colorscheme) section.
|
|
261
138
|
|
|
262
139
|
## Contributing
|
|
263
|
-
For
|
|
140
|
+
For Vue adapter-specific contributions, run the following commands to get started:
|
|
264
141
|
- `npm install`
|
|
265
|
-
- adjust the code in the `packages/
|
|
266
|
-
-
|
|
267
|
-
-
|
|
268
|
-
-
|
|
269
|
-
- update readme file in the `packages/angular` directory
|
|
142
|
+
- adjust the code in the `packages/vue` directory
|
|
143
|
+
- adjust the code in the `packages/vue/src/showcase` directory to make sure the changes can easily be seen in the example app
|
|
144
|
+
- `npm run dev` in the `packages/vue` directory to start the example app
|
|
145
|
+
- update readme file in the `packages/vue` directory
|
|
270
146
|
|
|
271
|
-
Before submitting a pull request, make sure to run the following commands in `packages/
|
|
147
|
+
Before submitting a pull request, make sure to run the following commands in `packages/vue` directory:
|
|
272
148
|
- `npm run lint`
|
|
273
149
|
- `npm run type-check`
|
|
274
150
|
- `npm run coverage`
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@skeletonizer/vue",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "1.1.0",
|
|
4
4
|
"description": "The way to skeletonize your Vue.js components",
|
|
5
5
|
"author": "Luka Varga",
|
|
6
6
|
"license": "MIT",
|
|
@@ -22,7 +22,7 @@
|
|
|
22
22
|
".": {
|
|
23
23
|
"import": "./dist/skeletonizer-vue.mjs",
|
|
24
24
|
"require": "./dist/skeletonizer-vue.umd.js",
|
|
25
|
-
"types": "./dist/index.d.ts"
|
|
25
|
+
"types": "./dist/src/lib/index.d.ts"
|
|
26
26
|
},
|
|
27
27
|
"./dist/*.css": "./dist/*.css"
|
|
28
28
|
},
|
|
@@ -46,37 +46,39 @@
|
|
|
46
46
|
"type-check": "vue-tsc --noEmit -p tsconfig.vitest.json --composite false",
|
|
47
47
|
"style-lint": "stylelint '**/*.?(css|scss|vue)' --color",
|
|
48
48
|
"style-lintfix": "stylelint '**/*.?(css|scss|vue)' --color --fix",
|
|
49
|
-
"lint": "eslint
|
|
50
|
-
"lintfix": "npm run style-lintfix && eslint
|
|
49
|
+
"lint": "eslint src/ && npm run style-lint",
|
|
50
|
+
"lintfix": "npm run style-lintfix && eslint src/ --fix",
|
|
51
51
|
"lint-staged": "lint-staged"
|
|
52
52
|
},
|
|
53
53
|
"peerDependencies": {
|
|
54
|
+
"@skeletonizer/utils": "^1.1.0",
|
|
54
55
|
"vue": "^3.3.4"
|
|
55
56
|
},
|
|
56
57
|
"devDependencies": {
|
|
58
|
+
"@skeletonizer/utils": "^1.1.0",
|
|
57
59
|
"@tsconfig/node18": "^2.0.1",
|
|
58
|
-
"@types/jsdom": "^21.1.
|
|
59
|
-
"@types/node": "^20.
|
|
60
|
+
"@types/jsdom": "^21.1.7",
|
|
61
|
+
"@types/node": "^20.17.5",
|
|
60
62
|
"@vitejs/plugin-vue": "^5.1.4",
|
|
61
|
-
"@vitest/browser": "2.1.
|
|
63
|
+
"@vitest/browser": "2.1.4",
|
|
62
64
|
"@vue/test-utils": "^2.4.6",
|
|
63
65
|
"@vue/tsconfig": "^0.5.1",
|
|
64
|
-
"eslint-plugin-vue": "^9.
|
|
65
|
-
"jsdom": "^
|
|
66
|
+
"eslint-plugin-vue": "^9.30.0",
|
|
67
|
+
"jsdom": "^25.0.1",
|
|
66
68
|
"npm-run-all": "^4.1.5",
|
|
67
|
-
"sass": "^1.
|
|
68
|
-
"typescript": "
|
|
69
|
-
"vite": "^5.4.
|
|
70
|
-
"vite-plugin-dts": "^4.
|
|
71
|
-
"vitest": "2.1.
|
|
72
|
-
"vue": "^3.5.
|
|
73
|
-
"vue-eslint-parser": "^9.4.
|
|
74
|
-
"vue-tsc": "^2.1.
|
|
75
|
-
"webdriverio": "^9.
|
|
69
|
+
"sass": "^1.80.5",
|
|
70
|
+
"typescript": "~5.5.4",
|
|
71
|
+
"vite": "^5.4.10",
|
|
72
|
+
"vite-plugin-dts": "^4.3.0",
|
|
73
|
+
"vitest": "2.1.4",
|
|
74
|
+
"vue": "^3.5.12",
|
|
75
|
+
"vue-eslint-parser": "^9.4.3",
|
|
76
|
+
"vue-tsc": "^2.1.10",
|
|
77
|
+
"webdriverio": "^9.2.8"
|
|
76
78
|
},
|
|
77
79
|
"lint-staged": {
|
|
78
80
|
"**/*.{scss,css}": "stylelint --fix",
|
|
79
81
|
"**/*.{ts,js,.vue}": "eslint --fix"
|
|
80
82
|
},
|
|
81
|
-
"gitHead": "
|
|
83
|
+
"gitHead": "1cc1b5c8a71f0f2490f555edf700c238a64df3d1"
|
|
82
84
|
}
|
|
@@ -1,78 +0,0 @@
|
|
|
1
|
-
import { ISkeletonizerColorSchema, TSchemaConfig } from '@skeletonizer/utils';
|
|
2
|
-
import { UnwrapRef } from 'vue';
|
|
3
|
-
declare const _default: <TSkeletonScopeObject extends object>(__VLS_props: {
|
|
4
|
-
config: TSchemaConfig<TSkeletonScopeObject>;
|
|
5
|
-
showSkeleton: boolean;
|
|
6
|
-
scope: TSkeletonScopeObject;
|
|
7
|
-
colorSchema?: ISkeletonizerColorSchema | undefined;
|
|
8
|
-
} & import('vue').VNodeProps & import('vue').AllowedComponentProps & import('vue').ComponentCustomProps, __VLS_ctx?: {
|
|
9
|
-
slots: Readonly<{
|
|
10
|
-
default?: ((props: {
|
|
11
|
-
scope: TSkeletonScopeObject | UnwrapRef<TSkeletonScopeObject>;
|
|
12
|
-
}) => {
|
|
13
|
-
scope: TSkeletonScopeObject | UnwrapRef<TSkeletonScopeObject>;
|
|
14
|
-
}) | undefined;
|
|
15
|
-
}> & {
|
|
16
|
-
default?: ((props: {
|
|
17
|
-
scope: TSkeletonScopeObject | UnwrapRef<TSkeletonScopeObject>;
|
|
18
|
-
}) => {
|
|
19
|
-
scope: TSkeletonScopeObject | UnwrapRef<TSkeletonScopeObject>;
|
|
20
|
-
}) | undefined;
|
|
21
|
-
};
|
|
22
|
-
attrs: any;
|
|
23
|
-
emit: {};
|
|
24
|
-
} | undefined, __VLS_expose?: ((exposed: import('vue').ShallowUnwrapRef<{}>) => void) | undefined, __VLS_setup?: Promise<{
|
|
25
|
-
props: {
|
|
26
|
-
config: TSchemaConfig<TSkeletonScopeObject>;
|
|
27
|
-
showSkeleton: boolean;
|
|
28
|
-
scope: TSkeletonScopeObject;
|
|
29
|
-
colorSchema?: ISkeletonizerColorSchema | undefined;
|
|
30
|
-
} & import('vue').VNodeProps & import('vue').AllowedComponentProps & import('vue').ComponentCustomProps;
|
|
31
|
-
expose(exposed: import('vue').ShallowUnwrapRef<{}>): void;
|
|
32
|
-
attrs: any;
|
|
33
|
-
slots: Readonly<{
|
|
34
|
-
default?: ((props: {
|
|
35
|
-
scope: TSkeletonScopeObject | UnwrapRef<TSkeletonScopeObject>;
|
|
36
|
-
}) => {
|
|
37
|
-
scope: TSkeletonScopeObject | UnwrapRef<TSkeletonScopeObject>;
|
|
38
|
-
}) | undefined;
|
|
39
|
-
}> & {
|
|
40
|
-
default?: ((props: {
|
|
41
|
-
scope: TSkeletonScopeObject | UnwrapRef<TSkeletonScopeObject>;
|
|
42
|
-
}) => {
|
|
43
|
-
scope: TSkeletonScopeObject | UnwrapRef<TSkeletonScopeObject>;
|
|
44
|
-
}) | undefined;
|
|
45
|
-
};
|
|
46
|
-
emit: {};
|
|
47
|
-
}>) => import('vue').VNode<import('vue').RendererNode, import('vue').RendererElement, {
|
|
48
|
-
[key: string]: any;
|
|
49
|
-
}> & {
|
|
50
|
-
__ctx?: {
|
|
51
|
-
props: {
|
|
52
|
-
config: TSchemaConfig<TSkeletonScopeObject>;
|
|
53
|
-
showSkeleton: boolean;
|
|
54
|
-
scope: TSkeletonScopeObject;
|
|
55
|
-
colorSchema?: ISkeletonizerColorSchema | undefined;
|
|
56
|
-
} & import('vue').VNodeProps & import('vue').AllowedComponentProps & import('vue').ComponentCustomProps;
|
|
57
|
-
expose(exposed: import('vue').ShallowUnwrapRef<{}>): void;
|
|
58
|
-
attrs: any;
|
|
59
|
-
slots: Readonly<{
|
|
60
|
-
default?: ((props: {
|
|
61
|
-
scope: TSkeletonScopeObject | UnwrapRef<TSkeletonScopeObject>;
|
|
62
|
-
}) => {
|
|
63
|
-
scope: TSkeletonScopeObject | UnwrapRef<TSkeletonScopeObject>;
|
|
64
|
-
}) | undefined;
|
|
65
|
-
}> & {
|
|
66
|
-
default?: ((props: {
|
|
67
|
-
scope: TSkeletonScopeObject | UnwrapRef<TSkeletonScopeObject>;
|
|
68
|
-
}) => {
|
|
69
|
-
scope: TSkeletonScopeObject | UnwrapRef<TSkeletonScopeObject>;
|
|
70
|
-
}) | undefined;
|
|
71
|
-
};
|
|
72
|
-
emit: {};
|
|
73
|
-
} | undefined;
|
|
74
|
-
};
|
|
75
|
-
export default _default;
|
|
76
|
-
type __VLS_PrettifyLocal<T> = {
|
|
77
|
-
[K in keyof T]: T[K];
|
|
78
|
-
} & {};
|
package/dist/index.css
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
[data-skeletonizer=wrapper-element]{--skeletonizer-text-background: rgba(0, 0, 0, .2);display:contents;filter:grayscale(100%);pointer-events:none}[data-skeletonizer=wrapper-element] *{pointer-events:none}[data-skeletonizer=wrapper-element] [data-skeletonizer=text]{animation:text-animation 2s infinite ease-in-out;background:var(--skeletonizer-primary-color);border-radius:50px;color:#0000!important}@keyframes text-animation{0%{background:var(--skeletonizer-primary-color)}50%{background:var(--skeletonizer-secondary-color)}to{background:var(--skeletonizer-primary-color)}}
|
package/dist/index.d.ts
DELETED
|
@@ -1,4 +0,0 @@
|
|
|
1
|
-
import { default as SkeletonizerSkeleton } from './components/SkeletonizerSkeleton.vue';
|
|
2
|
-
import { SkeletonizerComponentComposable } from './composables/skeletonizer.component.composable';
|
|
3
|
-
import { default as SkeletonizerPlugin } from './main';
|
|
4
|
-
export { SkeletonizerSkeleton, SkeletonizerComponentComposable, SkeletonizerPlugin };
|
|
@@ -1,53 +0,0 @@
|
|
|
1
|
-
import { defineComponent as m, reactive as l, watch as S, resolveDirective as u, openBlock as r, createElementBlock as s, Fragment as d, renderList as v, withDirectives as f, renderSlot as i } from "vue";
|
|
2
|
-
import { SkeletonAdapterComponent as h, SkeletonAbstractComponent as w, SkeletonDirective as z } from "@skeletonizer/utils";
|
|
3
|
-
const g = /* @__PURE__ */ m({
|
|
4
|
-
__name: "SkeletonizerSkeleton",
|
|
5
|
-
props: {
|
|
6
|
-
config: {},
|
|
7
|
-
showSkeleton: { type: Boolean },
|
|
8
|
-
scope: {},
|
|
9
|
-
colorSchema: {}
|
|
10
|
-
},
|
|
11
|
-
setup(n) {
|
|
12
|
-
const e = n, t = l(new h());
|
|
13
|
-
return S(
|
|
14
|
-
e.config,
|
|
15
|
-
(o) => {
|
|
16
|
-
t.config = o, t.setupModels();
|
|
17
|
-
},
|
|
18
|
-
{ immediate: !0 }
|
|
19
|
-
), (o, y) => {
|
|
20
|
-
const a = u("skeletonize");
|
|
21
|
-
return o.showSkeleton ? (r(!0), s(d, { key: 0 }, v(t.viewModels, (k, p) => f((r(), s("div", { key: p }, [
|
|
22
|
-
i(o.$slots, "default", {
|
|
23
|
-
scope: k.value
|
|
24
|
-
})
|
|
25
|
-
])), [
|
|
26
|
-
[a, e.colorSchema]
|
|
27
|
-
])), 128)) : i(o.$slots, "default", {
|
|
28
|
-
key: 1,
|
|
29
|
-
scope: e.scope
|
|
30
|
-
});
|
|
31
|
-
};
|
|
32
|
-
}
|
|
33
|
-
});
|
|
34
|
-
class c extends w {
|
|
35
|
-
constructor(e, t) {
|
|
36
|
-
super(), this.skeletonConfig = e, this.showSkeleton = t;
|
|
37
|
-
}
|
|
38
|
-
static generate(e, t) {
|
|
39
|
-
return l(new c(e, t));
|
|
40
|
-
}
|
|
41
|
-
}
|
|
42
|
-
const B = {
|
|
43
|
-
install: (n) => {
|
|
44
|
-
n.component("SkeletonizerSkeleton", g), n.directive("skeletonize", (e, t) => {
|
|
45
|
-
z.skeletonizeProjectedTemplate(e, t.value);
|
|
46
|
-
});
|
|
47
|
-
}
|
|
48
|
-
};
|
|
49
|
-
export {
|
|
50
|
-
c as SkeletonizerComponentComposable,
|
|
51
|
-
B as SkeletonizerPlugin,
|
|
52
|
-
g as SkeletonizerSkeleton
|
|
53
|
-
};
|
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
(function(t,e){typeof exports=="object"&&typeof module<"u"?e(exports,require("vue"),require("@skeletonizer/utils")):typeof define=="function"&&define.amd?define(["exports","vue","@skeletonizer/utils"],e):(t=typeof globalThis<"u"?globalThis:t||self,e(t.SkeletonizerVue={},t.Vue,t.SkeletonizerUtils))})(this,function(t,e,l){"use strict";var a=document.createElement("style");a.textContent=`[data-skeletonizer=wrapper-element]{--skeletonizer-text-background: rgba(0, 0, 0, .2);display:contents;filter:grayscale(100%);pointer-events:none}[data-skeletonizer=wrapper-element] *{pointer-events:none}[data-skeletonizer=wrapper-element] [data-skeletonizer=text]{animation:text-animation 2s infinite ease-in-out;background:var(--skeletonizer-primary-color);border-radius:50px;color:#0000!important}@keyframes text-animation{0%{background:var(--skeletonizer-primary-color)}50%{background:var(--skeletonizer-secondary-color)}to{background:var(--skeletonizer-primary-color)}}
|
|
2
|
-
`,document.head.appendChild(a);const c=e.defineComponent({__name:"SkeletonizerSkeleton",props:{config:{},showSkeleton:{type:Boolean},scope:{},colorSchema:{}},setup(i){const n=i,o=e.reactive(new l.SkeletonAdapterComponent);return e.watch(n.config,r=>{o.config=r,o.setupModels()},{immediate:!0}),(r,u)=>{const d=e.resolveDirective("skeletonize");return r.showSkeleton?(e.openBlock(!0),e.createElementBlock(e.Fragment,{key:0},e.renderList(o.viewModels,(p,m)=>e.withDirectives((e.openBlock(),e.createElementBlock("div",{key:m},[e.renderSlot(r.$slots,"default",{scope:p.value})])),[[d,n.colorSchema]])),128)):e.renderSlot(r.$slots,"default",{key:1,scope:n.scope})}}});class s extends l.SkeletonAbstractComponent{constructor(n,o){super(),this.skeletonConfig=n,this.showSkeleton=o}static generate(n,o){return e.reactive(new s(n,o))}}const k={install:i=>{i.component("SkeletonizerSkeleton",c),i.directive("skeletonize",(n,o)=>{l.SkeletonDirective.skeletonizeProjectedTemplate(n,o.value)})}};t.SkeletonizerComponentComposable=s,t.SkeletonizerPlugin=k,t.SkeletonizerSkeleton=c,Object.defineProperty(t,Symbol.toStringTag,{value:"Module"})});
|