@nuralyui/skeleton 0.0.1

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.
@@ -0,0 +1,387 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2023 Nuraly, Laabidi Aymen
4
+ * SPDX-License-Identifier: MIT
5
+ */
6
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
7
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
8
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
9
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
10
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
11
+ };
12
+ import { html, LitElement } from 'lit';
13
+ import { customElement, property } from 'lit/decorators.js';
14
+ import { classMap } from 'lit/directives/class-map.js';
15
+ import { styleMap } from 'lit/directives/style-map.js';
16
+ import { styles } from './skeleton.style.js';
17
+ import { NuralyUIBaseMixin } from '../../shared/base-mixin.js';
18
+ /**
19
+ * # Skeleton Component
20
+ *
21
+ * Provides a placeholder while content is loading, or to visualize content that doesn't exist yet.
22
+ * Improves perceived performance and user experience during data fetching.
23
+ *
24
+ * ## Features
25
+ * - Multiple skeleton elements (Avatar, Title, Paragraph, Button, Input, Image)
26
+ * - Active animation effect
27
+ * - Customizable shapes (circle, square, round)
28
+ * - Configurable sizes (small, default, large)
29
+ * - Loading state management
30
+ * - Theme-aware styling
31
+ * - Flexible configuration options
32
+ *
33
+ * ## Usage
34
+ * ```html
35
+ * <!-- Basic skeleton -->
36
+ * <nr-skeleton></nr-skeleton>
37
+ *
38
+ * <!-- With active animation -->
39
+ * <nr-skeleton active></nr-skeleton>
40
+ *
41
+ * <!-- Complex skeleton with avatar -->
42
+ * <nr-skeleton avatar active></nr-skeleton>
43
+ *
44
+ * <!-- Loading state with content -->
45
+ * <nr-skeleton loading>
46
+ * <div slot="content">
47
+ * <h3>Article Title</h3>
48
+ * <p>Article content goes here...</p>
49
+ * </div>
50
+ * </nr-skeleton>
51
+ *
52
+ * <!-- Skeleton button -->
53
+ * <nr-skeleton element="button" active></nr-skeleton>
54
+ *
55
+ * <!-- Skeleton input -->
56
+ * <nr-skeleton element="input" block></nr-skeleton>
57
+ * ```
58
+ *
59
+ * @element nr-skeleton
60
+ *
61
+ * @slot content - Content to show when loading is false
62
+ *
63
+ * @cssproperty --nuraly-skeleton-background - Background color of skeleton elements
64
+ * @cssproperty --nuraly-skeleton-gradient-from - Start color of active animation gradient
65
+ * @cssproperty --nuraly-skeleton-gradient-to - End color of active animation gradient
66
+ * @cssproperty --nuraly-skeleton-icon-color - Color of image placeholder icon
67
+ */
68
+ let NrSkeletonElement = class NrSkeletonElement extends NuralyUIBaseMixin(LitElement) {
69
+ constructor() {
70
+ super(...arguments);
71
+ /**
72
+ * Show animation effect
73
+ */
74
+ this.active = false;
75
+ /**
76
+ * Show avatar placeholder
77
+ */
78
+ this.avatar = false;
79
+ /**
80
+ * Avatar configuration
81
+ */
82
+ this.avatarConfig = {};
83
+ /**
84
+ * Display the skeleton when true
85
+ */
86
+ this.loading = true;
87
+ /**
88
+ * Show paragraph placeholder
89
+ */
90
+ this.paragraph = true;
91
+ /**
92
+ * Paragraph configuration
93
+ */
94
+ this.paragraphConfig = {};
95
+ /**
96
+ * Show paragraph and title radius when true
97
+ */
98
+ this.round = false;
99
+ /**
100
+ * Show title placeholder
101
+ */
102
+ this.showTitle = true;
103
+ /**
104
+ * Title configuration
105
+ */
106
+ this.titleConfig = {};
107
+ /**
108
+ * Button configuration
109
+ */
110
+ this.buttonConfig = {};
111
+ /**
112
+ * Input configuration
113
+ */
114
+ this.inputConfig = {};
115
+ /**
116
+ * Image configuration
117
+ */
118
+ this.imageConfig = {};
119
+ /**
120
+ * Block style for button/input
121
+ */
122
+ this.block = false;
123
+ /**
124
+ * Shape for standalone elements
125
+ */
126
+ this.shape = "default" /* SkeletonShape.Default */;
127
+ /**
128
+ * Size for standalone elements
129
+ */
130
+ this.size = "default" /* SkeletonSize.Default */;
131
+ }
132
+ /**
133
+ * Render avatar skeleton
134
+ */
135
+ renderAvatar() {
136
+ const config = typeof this.avatar === 'object' ? this.avatar : this.avatarConfig;
137
+ const shape = config.shape || "circle" /* SkeletonShape.Circle */;
138
+ const size = config.size || "default" /* SkeletonSize.Default */;
139
+ const sizeClass = typeof size === 'number' ? '' : size;
140
+ const customSize = typeof size === 'number' ? { width: `${size}px`, height: `${size}px` } : {};
141
+ return html `
142
+ <div
143
+ class=${classMap({
144
+ 'skeleton-avatar': true,
145
+ [`skeleton-avatar--${shape}`]: true,
146
+ [`skeleton-avatar--${sizeClass}`]: !!sizeClass,
147
+ })}
148
+ style=${styleMap(customSize)}></div>
149
+ `;
150
+ }
151
+ /**
152
+ * Render title skeleton
153
+ */
154
+ renderTitle() {
155
+ const config = typeof this.showTitle === 'object' ? this.showTitle : this.titleConfig;
156
+ const width = config.width;
157
+ const customWidth = width ? { width: typeof width === 'number' ? `${width}px` : width } : { width: '38%' };
158
+ return html `
159
+ <div
160
+ class=${classMap({
161
+ 'skeleton-title': true,
162
+ 'skeleton-title--round': this.round,
163
+ })}
164
+ style=${styleMap(customWidth)}></div>
165
+ `;
166
+ }
167
+ /**
168
+ * Render paragraph skeleton
169
+ */
170
+ renderParagraph() {
171
+ const config = typeof this.paragraph === 'object' ? this.paragraph : this.paragraphConfig;
172
+ const rows = config.rows || 3;
173
+ const widthConfig = config.width;
174
+ const getLineWidth = (index) => {
175
+ if (Array.isArray(widthConfig)) {
176
+ const width = widthConfig[index];
177
+ return width ? { width: typeof width === 'number' ? `${width}px` : width } : {};
178
+ }
179
+ // Last line uses custom width or 61%
180
+ if (index === rows - 1) {
181
+ if (widthConfig) {
182
+ return { width: typeof widthConfig === 'number' ? `${widthConfig}px` : widthConfig };
183
+ }
184
+ return { width: '61%' };
185
+ }
186
+ return {};
187
+ };
188
+ return html `
189
+ <div class="skeleton-paragraph">
190
+ ${Array.from({ length: rows }, (_, i) => html `
191
+ <div
192
+ class=${classMap({
193
+ 'skeleton-paragraph-line': true,
194
+ 'skeleton-paragraph-line--round': this.round,
195
+ })}
196
+ style=${styleMap(getLineWidth(i))}></div>
197
+ `)}
198
+ </div>
199
+ `;
200
+ }
201
+ /**
202
+ * Render button skeleton
203
+ */
204
+ renderButton() {
205
+ const config = this.buttonConfig;
206
+ const buttonShape = config.shape || this.shape;
207
+ const buttonSize = config.size || this.size;
208
+ const buttonBlock = config.block !== undefined ? config.block : this.block;
209
+ return html `
210
+ <div
211
+ class=${classMap({
212
+ 'skeleton-button': true,
213
+ [`skeleton-button--${buttonShape}`]: true,
214
+ [`skeleton-button--${buttonSize}`]: true,
215
+ 'skeleton-button--block': buttonBlock,
216
+ })}></div>
217
+ `;
218
+ }
219
+ /**
220
+ * Render input skeleton
221
+ */
222
+ renderInput() {
223
+ const config = this.inputConfig;
224
+ const inputSize = config.size || this.size;
225
+ const inputBlock = config.block !== undefined ? config.block : this.block;
226
+ return html `
227
+ <div
228
+ class=${classMap({
229
+ 'skeleton-input': true,
230
+ [`skeleton-input--${inputSize}`]: true,
231
+ 'skeleton-input--block': inputBlock,
232
+ })}></div>
233
+ `;
234
+ }
235
+ /**
236
+ * Render image skeleton
237
+ */
238
+ renderImage() {
239
+ return html `
240
+ <div class="skeleton-image">
241
+ <svg
242
+ class="skeleton-image-icon"
243
+ viewBox="0 0 1024 1024"
244
+ xmlns="http://www.w3.org/2000/svg"
245
+ width="48"
246
+ height="48">
247
+ <path
248
+ d="M928 160H96c-17.7 0-32 14.3-32 32v640c0 17.7 14.3 32 32 32h832c17.7 0 32-14.3 32-32V192c0-17.7-14.3-32-32-32zM338 304c35.3 0 64 28.7 64 64s-28.7 64-64 64-64-28.7-64-64 28.7-64 64-64zm513.9 437.1c-2.1 2.1-4.5 3.8-7 5.1-5.2 2.7-11.1 4.1-17.1 4.1H196.2c-6 0-11.9-1.4-17.1-4.1-2.5-1.3-4.9-3-7-5.1-4.4-4.4-7.1-10.5-7.1-17.1 0-3.7.8-7.4 2.5-10.8 1.6-3.4 4.1-6.4 7.1-8.8l112.3-97.5c8.8-7.6 22.1-7.6 30.9 0l148.5 129 203.9-177c8.8-7.6 22.1-7.6 30.9 0l179.8 156.1c3 2.6 5.5 5.7 7.1 9.3 1.7 3.7 2.5 7.6 2.5 11.6-.1 6.6-2.8 12.7-7.2 17.1z"
249
+ fill="currentColor" />
250
+ </svg>
251
+ </div>
252
+ `;
253
+ }
254
+ /**
255
+ * Render standalone element
256
+ */
257
+ renderStandaloneElement() {
258
+ switch (this.element) {
259
+ case "button" /* SkeletonElementType.Button */:
260
+ return this.renderButton();
261
+ case "input" /* SkeletonElementType.Input */:
262
+ return this.renderInput();
263
+ case "image" /* SkeletonElementType.Image */:
264
+ return this.renderImage();
265
+ case "avatar" /* SkeletonElementType.Avatar */:
266
+ return this.renderAvatar();
267
+ default:
268
+ return html ``;
269
+ }
270
+ }
271
+ /**
272
+ * Render full skeleton
273
+ */
274
+ renderSkeleton() {
275
+ // If element type is specified, render standalone element
276
+ if (this.element) {
277
+ return html `
278
+ <div
279
+ class=${classMap({
280
+ 'skeleton': true,
281
+ 'skeleton--active': this.active || (this.element === "avatar" /* SkeletonElementType.Avatar */ && !!this.avatarConfig.active),
282
+ })}>
283
+ ${this.renderStandaloneElement()}
284
+ </div>
285
+ `;
286
+ }
287
+ // Render full skeleton layout
288
+ return html `
289
+ <div
290
+ class=${classMap({
291
+ 'skeleton': true,
292
+ 'skeleton--active': this.active,
293
+ })}>
294
+ ${this.avatar || this.showTitle || this.paragraph
295
+ ? html `
296
+ ${this.avatar
297
+ ? html `
298
+ <div class="skeleton-header">
299
+ ${this.renderAvatar()}
300
+ ${this.showTitle || this.paragraph
301
+ ? html `
302
+ <div class="skeleton-content">
303
+ ${this.showTitle ? this.renderTitle() : ''}
304
+ ${this.paragraph ? this.renderParagraph() : ''}
305
+ </div>
306
+ `
307
+ : ''}
308
+ </div>
309
+ `
310
+ : html `
311
+ <div class="skeleton-content">
312
+ ${this.showTitle ? this.renderTitle() : ''}
313
+ ${this.paragraph ? this.renderParagraph() : ''}
314
+ </div>
315
+ `}
316
+ `
317
+ : ''}
318
+ </div>
319
+ `;
320
+ }
321
+ render() {
322
+ // If loading is false, show slotted content
323
+ if (!this.loading) {
324
+ return html `
325
+ <div class="skeleton-wrapper">
326
+ <slot name="content"><slot></slot></slot>
327
+ </div>
328
+ `;
329
+ }
330
+ // Show skeleton
331
+ return this.renderSkeleton();
332
+ }
333
+ };
334
+ NrSkeletonElement.styles = styles;
335
+ __decorate([
336
+ property({ type: Boolean })
337
+ ], NrSkeletonElement.prototype, "active", void 0);
338
+ __decorate([
339
+ property({ type: Boolean })
340
+ ], NrSkeletonElement.prototype, "avatar", void 0);
341
+ __decorate([
342
+ property({ type: Object, attribute: 'avatar-config' })
343
+ ], NrSkeletonElement.prototype, "avatarConfig", void 0);
344
+ __decorate([
345
+ property({ type: Boolean })
346
+ ], NrSkeletonElement.prototype, "loading", void 0);
347
+ __decorate([
348
+ property({ type: Boolean })
349
+ ], NrSkeletonElement.prototype, "paragraph", void 0);
350
+ __decorate([
351
+ property({ type: Object, attribute: 'paragraph-config' })
352
+ ], NrSkeletonElement.prototype, "paragraphConfig", void 0);
353
+ __decorate([
354
+ property({ type: Boolean })
355
+ ], NrSkeletonElement.prototype, "round", void 0);
356
+ __decorate([
357
+ property({ type: Boolean, attribute: 'show-title' })
358
+ ], NrSkeletonElement.prototype, "showTitle", void 0);
359
+ __decorate([
360
+ property({ type: Object, attribute: 'title-config' })
361
+ ], NrSkeletonElement.prototype, "titleConfig", void 0);
362
+ __decorate([
363
+ property({ type: String })
364
+ ], NrSkeletonElement.prototype, "element", void 0);
365
+ __decorate([
366
+ property({ type: Object, attribute: 'button-config' })
367
+ ], NrSkeletonElement.prototype, "buttonConfig", void 0);
368
+ __decorate([
369
+ property({ type: Object, attribute: 'input-config' })
370
+ ], NrSkeletonElement.prototype, "inputConfig", void 0);
371
+ __decorate([
372
+ property({ type: Object, attribute: 'image-config' })
373
+ ], NrSkeletonElement.prototype, "imageConfig", void 0);
374
+ __decorate([
375
+ property({ type: Boolean })
376
+ ], NrSkeletonElement.prototype, "block", void 0);
377
+ __decorate([
378
+ property({ type: String })
379
+ ], NrSkeletonElement.prototype, "shape", void 0);
380
+ __decorate([
381
+ property({ type: String })
382
+ ], NrSkeletonElement.prototype, "size", void 0);
383
+ NrSkeletonElement = __decorate([
384
+ customElement('nr-skeleton')
385
+ ], NrSkeletonElement);
386
+ export { NrSkeletonElement };
387
+ //# sourceMappingURL=skeleton.component.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"skeleton.component.js","sourceRoot":"","sources":["../../../src/components/skeleton/skeleton.component.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * @license\n * Copyright 2023 Nuraly, Laabidi Aymen\n * SPDX-License-Identifier: MIT\n */\n\nimport { html, LitElement } from 'lit';\nimport { customElement, property } from 'lit/decorators.js';\nimport { classMap } from 'lit/directives/class-map.js';\nimport { styleMap } from 'lit/directives/style-map.js';\nimport { styles } from './skeleton.style.js';\nimport { NuralyUIBaseMixin } from '../../shared/base-mixin.js';\nimport {\n SkeletonShape,\n SkeletonSize,\n SkeletonElementType,\n SkeletonAvatarConfig,\n SkeletonTitleConfig,\n SkeletonParagraphConfig,\n SkeletonButtonConfig,\n SkeletonInputConfig,\n SkeletonImageConfig,\n} from './skeleton.types.js';\n\n/**\n * # Skeleton Component\n *\n * Provides a placeholder while content is loading, or to visualize content that doesn't exist yet.\n * Improves perceived performance and user experience during data fetching.\n *\n * ## Features\n * - Multiple skeleton elements (Avatar, Title, Paragraph, Button, Input, Image)\n * - Active animation effect\n * - Customizable shapes (circle, square, round)\n * - Configurable sizes (small, default, large)\n * - Loading state management\n * - Theme-aware styling\n * - Flexible configuration options\n *\n * ## Usage\n * ```html\n * <!-- Basic skeleton -->\n * <nr-skeleton></nr-skeleton>\n *\n * <!-- With active animation -->\n * <nr-skeleton active></nr-skeleton>\n *\n * <!-- Complex skeleton with avatar -->\n * <nr-skeleton avatar active></nr-skeleton>\n *\n * <!-- Loading state with content -->\n * <nr-skeleton loading>\n * <div slot=\"content\">\n * <h3>Article Title</h3>\n * <p>Article content goes here...</p>\n * </div>\n * </nr-skeleton>\n *\n * <!-- Skeleton button -->\n * <nr-skeleton element=\"button\" active></nr-skeleton>\n *\n * <!-- Skeleton input -->\n * <nr-skeleton element=\"input\" block></nr-skeleton>\n * ```\n *\n * @element nr-skeleton\n *\n * @slot content - Content to show when loading is false\n *\n * @cssproperty --nuraly-skeleton-background - Background color of skeleton elements\n * @cssproperty --nuraly-skeleton-gradient-from - Start color of active animation gradient\n * @cssproperty --nuraly-skeleton-gradient-to - End color of active animation gradient\n * @cssproperty --nuraly-skeleton-icon-color - Color of image placeholder icon\n */\n@customElement('nr-skeleton')\nexport class NrSkeletonElement extends NuralyUIBaseMixin(LitElement) {\n static override styles = styles;\n\n /**\n * Show animation effect\n */\n @property({ type: Boolean }) active = false;\n\n /**\n * Show avatar placeholder\n */\n @property({ type: Boolean }) avatar = false;\n\n /**\n * Avatar configuration\n */\n @property({ type: Object, attribute: 'avatar-config' }) avatarConfig: SkeletonAvatarConfig = {};\n\n /**\n * Display the skeleton when true\n */\n @property({ type: Boolean }) loading = true;\n\n /**\n * Show paragraph placeholder\n */\n @property({ type: Boolean }) paragraph = true;\n\n /**\n * Paragraph configuration\n */\n @property({ type: Object, attribute: 'paragraph-config' }) paragraphConfig: SkeletonParagraphConfig = {};\n\n /**\n * Show paragraph and title radius when true\n */\n @property({ type: Boolean }) round = false;\n\n /**\n * Show title placeholder\n */\n @property({ type: Boolean, attribute: 'show-title' }) showTitle = true;\n\n /**\n * Title configuration\n */\n @property({ type: Object, attribute: 'title-config' }) titleConfig: SkeletonTitleConfig = {};\n\n /**\n * Element type for standalone skeleton elements\n */\n @property({ type: String }) element?: SkeletonElementType;\n\n /**\n * Button configuration\n */\n @property({ type: Object, attribute: 'button-config' }) buttonConfig: SkeletonButtonConfig = {};\n\n /**\n * Input configuration\n */\n @property({ type: Object, attribute: 'input-config' }) inputConfig: SkeletonInputConfig = {};\n\n /**\n * Image configuration\n */\n @property({ type: Object, attribute: 'image-config' }) imageConfig: SkeletonImageConfig = {};\n\n /**\n * Block style for button/input\n */\n @property({ type: Boolean }) block = false;\n\n /**\n * Shape for standalone elements\n */\n @property({ type: String }) shape: SkeletonShape = SkeletonShape.Default;\n\n /**\n * Size for standalone elements\n */\n @property({ type: String }) size: SkeletonSize = SkeletonSize.Default;\n\n /**\n * Render avatar skeleton\n */\n private renderAvatar() {\n const config = typeof this.avatar === 'object' ? this.avatar : this.avatarConfig;\n const shape = config.shape || SkeletonShape.Circle;\n const size = config.size || SkeletonSize.Default;\n \n const sizeClass = typeof size === 'number' ? '' : size;\n const customSize = typeof size === 'number' ? { width: `${size}px`, height: `${size}px` } : {};\n\n return html`\n <div\n class=${classMap({\n 'skeleton-avatar': true,\n [`skeleton-avatar--${shape}`]: true,\n [`skeleton-avatar--${sizeClass}`]: !!sizeClass,\n })}\n style=${styleMap(customSize)}></div>\n `;\n }\n\n /**\n * Render title skeleton\n */\n private renderTitle() {\n const config = typeof this.showTitle === 'object' ? this.showTitle as any : this.titleConfig;\n const width = config.width;\n const customWidth = width ? { width: typeof width === 'number' ? `${width}px` : width } : { width: '38%' };\n\n return html`\n <div\n class=${classMap({\n 'skeleton-title': true,\n 'skeleton-title--round': this.round,\n })}\n style=${styleMap(customWidth)}></div>\n `;\n }\n\n /**\n * Render paragraph skeleton\n */\n private renderParagraph() {\n const config = typeof this.paragraph === 'object' ? this.paragraph : this.paragraphConfig;\n const rows = config.rows || 3;\n const widthConfig = config.width;\n\n const getLineWidth = (index: number): Record<string, string> => {\n if (Array.isArray(widthConfig)) {\n const width = widthConfig[index];\n return width ? { width: typeof width === 'number' ? `${width}px` : width } : {};\n }\n \n // Last line uses custom width or 61%\n if (index === rows - 1) {\n if (widthConfig) {\n return { width: typeof widthConfig === 'number' ? `${widthConfig}px` : widthConfig };\n }\n return { width: '61%' };\n }\n \n return {};\n };\n\n return html`\n <div class=\"skeleton-paragraph\">\n ${Array.from({ length: rows }, (_, i) => html`\n <div\n class=${classMap({\n 'skeleton-paragraph-line': true,\n 'skeleton-paragraph-line--round': this.round,\n })}\n style=${styleMap(getLineWidth(i))}></div>\n `)}\n </div>\n `;\n }\n\n /**\n * Render button skeleton\n */\n private renderButton() {\n const config = this.buttonConfig;\n const buttonShape = config.shape || this.shape;\n const buttonSize = config.size || this.size;\n const buttonBlock = config.block !== undefined ? config.block : this.block;\n\n return html`\n <div\n class=${classMap({\n 'skeleton-button': true,\n [`skeleton-button--${buttonShape}`]: true,\n [`skeleton-button--${buttonSize}`]: true,\n 'skeleton-button--block': buttonBlock,\n })}></div>\n `;\n }\n\n /**\n * Render input skeleton\n */\n private renderInput() {\n const config = this.inputConfig;\n const inputSize = config.size || this.size;\n const inputBlock = config.block !== undefined ? config.block : this.block;\n\n return html`\n <div\n class=${classMap({\n 'skeleton-input': true,\n [`skeleton-input--${inputSize}`]: true,\n 'skeleton-input--block': inputBlock,\n })}></div>\n `;\n }\n\n /**\n * Render image skeleton\n */\n private renderImage() {\n return html`\n <div class=\"skeleton-image\">\n <svg\n class=\"skeleton-image-icon\"\n viewBox=\"0 0 1024 1024\"\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"48\"\n height=\"48\">\n <path\n d=\"M928 160H96c-17.7 0-32 14.3-32 32v640c0 17.7 14.3 32 32 32h832c17.7 0 32-14.3 32-32V192c0-17.7-14.3-32-32-32zM338 304c35.3 0 64 28.7 64 64s-28.7 64-64 64-64-28.7-64-64 28.7-64 64-64zm513.9 437.1c-2.1 2.1-4.5 3.8-7 5.1-5.2 2.7-11.1 4.1-17.1 4.1H196.2c-6 0-11.9-1.4-17.1-4.1-2.5-1.3-4.9-3-7-5.1-4.4-4.4-7.1-10.5-7.1-17.1 0-3.7.8-7.4 2.5-10.8 1.6-3.4 4.1-6.4 7.1-8.8l112.3-97.5c8.8-7.6 22.1-7.6 30.9 0l148.5 129 203.9-177c8.8-7.6 22.1-7.6 30.9 0l179.8 156.1c3 2.6 5.5 5.7 7.1 9.3 1.7 3.7 2.5 7.6 2.5 11.6-.1 6.6-2.8 12.7-7.2 17.1z\"\n fill=\"currentColor\" />\n </svg>\n </div>\n `;\n }\n\n /**\n * Render standalone element\n */\n private renderStandaloneElement() {\n switch (this.element) {\n case SkeletonElementType.Button:\n return this.renderButton();\n case SkeletonElementType.Input:\n return this.renderInput();\n case SkeletonElementType.Image:\n return this.renderImage();\n case SkeletonElementType.Avatar:\n return this.renderAvatar();\n default:\n return html``;\n }\n }\n\n /**\n * Render full skeleton\n */\n private renderSkeleton() {\n // If element type is specified, render standalone element\n if (this.element) {\n return html`\n <div\n class=${classMap({\n 'skeleton': true,\n 'skeleton--active': this.active || (this.element === SkeletonElementType.Avatar && !!this.avatarConfig.active),\n })}>\n ${this.renderStandaloneElement()}\n </div>\n `;\n }\n\n // Render full skeleton layout\n return html`\n <div\n class=${classMap({\n 'skeleton': true,\n 'skeleton--active': this.active,\n })}>\n ${this.avatar || this.showTitle || this.paragraph\n ? html`\n ${this.avatar\n ? html`\n <div class=\"skeleton-header\">\n ${this.renderAvatar()}\n ${this.showTitle || this.paragraph\n ? html`\n <div class=\"skeleton-content\">\n ${this.showTitle ? this.renderTitle() : ''}\n ${this.paragraph ? this.renderParagraph() : ''}\n </div>\n `\n : ''}\n </div>\n `\n : html`\n <div class=\"skeleton-content\">\n ${this.showTitle ? this.renderTitle() : ''}\n ${this.paragraph ? this.renderParagraph() : ''}\n </div>\n `}\n `\n : ''}\n </div>\n `;\n }\n\n override render() {\n // If loading is false, show slotted content\n if (!this.loading) {\n return html`\n <div class=\"skeleton-wrapper\">\n <slot name=\"content\"><slot></slot></slot>\n </div>\n `;\n }\n\n // Show skeleton\n return this.renderSkeleton();\n }\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'nr-skeleton': NrSkeletonElement;\n }\n}\n"]}
@@ -0,0 +1,2 @@
1
+ export declare const styles: import("lit").CSSResult;
2
+ //# sourceMappingURL=skeleton.style.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"skeleton.style.d.ts","sourceRoot":"","sources":["../../../src/components/skeleton/skeleton.style.ts"],"names":[],"mappings":"AAEA,eAAO,MAAM,MAAM,yBA6NlB,CAAC"}
@@ -0,0 +1,224 @@
1
+ import { css } from 'lit';
2
+ export const styles = css `
3
+ :host {
4
+ display: block;
5
+ }
6
+
7
+ .skeleton {
8
+ display: flex;
9
+ flex-direction: column;
10
+ gap: 16px;
11
+ }
12
+
13
+ .skeleton-header {
14
+ display: flex;
15
+ align-items: center;
16
+ gap: 16px;
17
+ }
18
+
19
+ .skeleton-content {
20
+ flex: 1;
21
+ }
22
+
23
+ /* Avatar */
24
+ .skeleton-avatar {
25
+ flex-shrink: 0;
26
+ background: var(--nuraly-skeleton-background, rgba(0, 0, 0, 0.06));
27
+ border-radius: 4px;
28
+ }
29
+
30
+ .skeleton-avatar--circle {
31
+ border-radius: 50%;
32
+ }
33
+
34
+ .skeleton-avatar--square {
35
+ border-radius: 4px;
36
+ }
37
+
38
+ .skeleton-avatar--small {
39
+ width: 32px;
40
+ height: 32px;
41
+ }
42
+
43
+ .skeleton-avatar--default {
44
+ width: 40px;
45
+ height: 40px;
46
+ }
47
+
48
+ .skeleton-avatar--large {
49
+ width: 48px;
50
+ height: 48px;
51
+ }
52
+
53
+ /* Title */
54
+ .skeleton-title {
55
+ height: 16px;
56
+ background: var(--nuraly-skeleton-background, rgba(0, 0, 0, 0.06));
57
+ border-radius: 4px;
58
+ margin-bottom: 12px;
59
+ }
60
+
61
+ .skeleton-title--round {
62
+ border-radius: 8px;
63
+ }
64
+
65
+ /* Paragraph */
66
+ .skeleton-paragraph {
67
+ display: flex;
68
+ flex-direction: column;
69
+ gap: 12px;
70
+ }
71
+
72
+ .skeleton-paragraph-line {
73
+ height: 16px;
74
+ background: var(--nuraly-skeleton-background, rgba(0, 0, 0, 0.06));
75
+ border-radius: 4px;
76
+ }
77
+
78
+ .skeleton-paragraph-line--round {
79
+ border-radius: 8px;
80
+ }
81
+
82
+ /* Button */
83
+ .skeleton-button {
84
+ display: inline-block;
85
+ background: var(--nuraly-skeleton-background, rgba(0, 0, 0, 0.06));
86
+ border-radius: 4px;
87
+ }
88
+
89
+ .skeleton-button--block {
90
+ display: block;
91
+ width: 100%;
92
+ }
93
+
94
+ .skeleton-button--circle {
95
+ border-radius: 50%;
96
+ }
97
+
98
+ .skeleton-button--round {
99
+ border-radius: 16px;
100
+ }
101
+
102
+ .skeleton-button--square {
103
+ border-radius: 4px;
104
+ }
105
+
106
+ .skeleton-button--small {
107
+ width: 64px;
108
+ height: 24px;
109
+ }
110
+
111
+ .skeleton-button--default {
112
+ width: 80px;
113
+ height: 32px;
114
+ }
115
+
116
+ .skeleton-button--large {
117
+ width: 96px;
118
+ height: 40px;
119
+ }
120
+
121
+ /* Input */
122
+ .skeleton-input {
123
+ display: block;
124
+ background: var(--nuraly-skeleton-background, rgba(0, 0, 0, 0.06));
125
+ border-radius: 4px;
126
+ }
127
+
128
+ .skeleton-input--small {
129
+ height: 24px;
130
+ }
131
+
132
+ .skeleton-input--default {
133
+ height: 32px;
134
+ }
135
+
136
+ .skeleton-input--large {
137
+ height: 40px;
138
+ }
139
+
140
+ .skeleton-input--block {
141
+ width: 100%;
142
+ }
143
+
144
+ /* Image */
145
+ .skeleton-image {
146
+ display: flex;
147
+ align-items: center;
148
+ justify-content: center;
149
+ background: var(--nuraly-skeleton-background, rgba(0, 0, 0, 0.06));
150
+ border-radius: 4px;
151
+ width: 100%;
152
+ height: 200px;
153
+ }
154
+
155
+ .skeleton-image-icon {
156
+ font-size: 48px;
157
+ color: var(--nuraly-skeleton-icon-color, rgba(0, 0, 0, 0.15));
158
+ }
159
+
160
+ /* Active animation */
161
+ @keyframes skeleton-loading {
162
+ 0% {
163
+ background-position: 100% 50%;
164
+ }
165
+ 100% {
166
+ background-position: 0 50%;
167
+ }
168
+ }
169
+
170
+ .skeleton--active .skeleton-avatar,
171
+ .skeleton--active .skeleton-title,
172
+ .skeleton--active .skeleton-paragraph-line,
173
+ .skeleton--active .skeleton-button,
174
+ .skeleton--active .skeleton-input,
175
+ .skeleton--active .skeleton-image {
176
+ background: linear-gradient(
177
+ 90deg,
178
+ var(--nuraly-skeleton-gradient-from, rgba(0, 0, 0, 0.06)) 25%,
179
+ var(--nuraly-skeleton-gradient-to, rgba(0, 0, 0, 0.15)) 37%,
180
+ var(--nuraly-skeleton-gradient-from, rgba(0, 0, 0, 0.06)) 63%
181
+ );
182
+ background-size: 400% 100%;
183
+ animation: skeleton-loading 1.4s ease infinite;
184
+ }
185
+
186
+ /* Dark theme support */
187
+ :host([theme='carbon-dark']) .skeleton-avatar,
188
+ :host([theme='carbon-dark']) .skeleton-title,
189
+ :host([theme='carbon-dark']) .skeleton-paragraph-line,
190
+ :host([theme='carbon-dark']) .skeleton-button,
191
+ :host([theme='carbon-dark']) .skeleton-input,
192
+ :host([theme='carbon-dark']) .skeleton-image {
193
+ background: rgba(255, 255, 255, 0.08);
194
+ }
195
+
196
+ :host([theme='carbon-dark']) .skeleton-image-icon {
197
+ color: rgba(255, 255, 255, 0.15);
198
+ }
199
+
200
+ :host([theme='carbon-dark']) .skeleton--active .skeleton-avatar,
201
+ :host([theme='carbon-dark']) .skeleton--active .skeleton-title,
202
+ :host([theme='carbon-dark']) .skeleton--active .skeleton-paragraph-line,
203
+ :host([theme='carbon-dark']) .skeleton--active .skeleton-button,
204
+ :host([theme='carbon-dark']) .skeleton--active .skeleton-input,
205
+ :host([theme='carbon-dark']) .skeleton--active .skeleton-image {
206
+ background: linear-gradient(
207
+ 90deg,
208
+ rgba(255, 255, 255, 0.08) 25%,
209
+ rgba(255, 255, 255, 0.15) 37%,
210
+ rgba(255, 255, 255, 0.08) 63%
211
+ );
212
+ background-size: 400% 100%;
213
+ }
214
+
215
+ /* Content wrapper for loading state */
216
+ .skeleton-wrapper {
217
+ display: block;
218
+ }
219
+
220
+ .skeleton-wrapper--hidden {
221
+ display: none;
222
+ }
223
+ `;
224
+ //# sourceMappingURL=skeleton.style.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"skeleton.style.js","sourceRoot":"","sources":["../../../src/components/skeleton/skeleton.style.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,EAAE,MAAM,KAAK,CAAC;AAE1B,MAAM,CAAC,MAAM,MAAM,GAAG,GAAG,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA6NxB,CAAC","sourcesContent":["import { css } from 'lit';\n\nexport const styles = css`\n :host {\n display: block;\n }\n\n .skeleton {\n display: flex;\n flex-direction: column;\n gap: 16px;\n }\n\n .skeleton-header {\n display: flex;\n align-items: center;\n gap: 16px;\n }\n\n .skeleton-content {\n flex: 1;\n }\n\n /* Avatar */\n .skeleton-avatar {\n flex-shrink: 0;\n background: var(--nuraly-skeleton-background, rgba(0, 0, 0, 0.06));\n border-radius: 4px;\n }\n\n .skeleton-avatar--circle {\n border-radius: 50%;\n }\n\n .skeleton-avatar--square {\n border-radius: 4px;\n }\n\n .skeleton-avatar--small {\n width: 32px;\n height: 32px;\n }\n\n .skeleton-avatar--default {\n width: 40px;\n height: 40px;\n }\n\n .skeleton-avatar--large {\n width: 48px;\n height: 48px;\n }\n\n /* Title */\n .skeleton-title {\n height: 16px;\n background: var(--nuraly-skeleton-background, rgba(0, 0, 0, 0.06));\n border-radius: 4px;\n margin-bottom: 12px;\n }\n\n .skeleton-title--round {\n border-radius: 8px;\n }\n\n /* Paragraph */\n .skeleton-paragraph {\n display: flex;\n flex-direction: column;\n gap: 12px;\n }\n\n .skeleton-paragraph-line {\n height: 16px;\n background: var(--nuraly-skeleton-background, rgba(0, 0, 0, 0.06));\n border-radius: 4px;\n }\n\n .skeleton-paragraph-line--round {\n border-radius: 8px;\n }\n\n /* Button */\n .skeleton-button {\n display: inline-block;\n background: var(--nuraly-skeleton-background, rgba(0, 0, 0, 0.06));\n border-radius: 4px;\n }\n\n .skeleton-button--block {\n display: block;\n width: 100%;\n }\n\n .skeleton-button--circle {\n border-radius: 50%;\n }\n\n .skeleton-button--round {\n border-radius: 16px;\n }\n\n .skeleton-button--square {\n border-radius: 4px;\n }\n\n .skeleton-button--small {\n width: 64px;\n height: 24px;\n }\n\n .skeleton-button--default {\n width: 80px;\n height: 32px;\n }\n\n .skeleton-button--large {\n width: 96px;\n height: 40px;\n }\n\n /* Input */\n .skeleton-input {\n display: block;\n background: var(--nuraly-skeleton-background, rgba(0, 0, 0, 0.06));\n border-radius: 4px;\n }\n\n .skeleton-input--small {\n height: 24px;\n }\n\n .skeleton-input--default {\n height: 32px;\n }\n\n .skeleton-input--large {\n height: 40px;\n }\n\n .skeleton-input--block {\n width: 100%;\n }\n\n /* Image */\n .skeleton-image {\n display: flex;\n align-items: center;\n justify-content: center;\n background: var(--nuraly-skeleton-background, rgba(0, 0, 0, 0.06));\n border-radius: 4px;\n width: 100%;\n height: 200px;\n }\n\n .skeleton-image-icon {\n font-size: 48px;\n color: var(--nuraly-skeleton-icon-color, rgba(0, 0, 0, 0.15));\n }\n\n /* Active animation */\n @keyframes skeleton-loading {\n 0% {\n background-position: 100% 50%;\n }\n 100% {\n background-position: 0 50%;\n }\n }\n\n .skeleton--active .skeleton-avatar,\n .skeleton--active .skeleton-title,\n .skeleton--active .skeleton-paragraph-line,\n .skeleton--active .skeleton-button,\n .skeleton--active .skeleton-input,\n .skeleton--active .skeleton-image {\n background: linear-gradient(\n 90deg,\n var(--nuraly-skeleton-gradient-from, rgba(0, 0, 0, 0.06)) 25%,\n var(--nuraly-skeleton-gradient-to, rgba(0, 0, 0, 0.15)) 37%,\n var(--nuraly-skeleton-gradient-from, rgba(0, 0, 0, 0.06)) 63%\n );\n background-size: 400% 100%;\n animation: skeleton-loading 1.4s ease infinite;\n }\n\n /* Dark theme support */\n :host([theme='carbon-dark']) .skeleton-avatar,\n :host([theme='carbon-dark']) .skeleton-title,\n :host([theme='carbon-dark']) .skeleton-paragraph-line,\n :host([theme='carbon-dark']) .skeleton-button,\n :host([theme='carbon-dark']) .skeleton-input,\n :host([theme='carbon-dark']) .skeleton-image {\n background: rgba(255, 255, 255, 0.08);\n }\n\n :host([theme='carbon-dark']) .skeleton-image-icon {\n color: rgba(255, 255, 255, 0.15);\n }\n\n :host([theme='carbon-dark']) .skeleton--active .skeleton-avatar,\n :host([theme='carbon-dark']) .skeleton--active .skeleton-title,\n :host([theme='carbon-dark']) .skeleton--active .skeleton-paragraph-line,\n :host([theme='carbon-dark']) .skeleton--active .skeleton-button,\n :host([theme='carbon-dark']) .skeleton--active .skeleton-input,\n :host([theme='carbon-dark']) .skeleton--active .skeleton-image {\n background: linear-gradient(\n 90deg,\n rgba(255, 255, 255, 0.08) 25%,\n rgba(255, 255, 255, 0.15) 37%,\n rgba(255, 255, 255, 0.08) 63%\n );\n background-size: 400% 100%;\n }\n\n /* Content wrapper for loading state */\n .skeleton-wrapper {\n display: block;\n }\n\n .skeleton-wrapper--hidden {\n display: none;\n }\n`;\n"]}