@danielito1996/compose-svelted 0.2.7-alpha02 → 0.2.7-alpha03
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/dist/components/layouts/LazyColumn.svelte +12 -12
- package/dist/components/layouts/LazyRow.svelte +81 -45
- package/dist/components/layouts/LazyRow.svelte.d.ts +3 -6
- package/dist/components/layouts/Scaffold.svelte +19 -39
- package/dist/components/layouts/Scaffold.svelte.d.ts +2 -1
- package/dist/core/styles/baseline.css +49 -0
- package/dist/index.js +1 -0
- package/package.json +3 -2
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
let scrollTop = 0;
|
|
19
19
|
let viewportHeight = 0;
|
|
20
20
|
|
|
21
|
-
let estimatedItemHeight = 56;
|
|
21
|
+
let estimatedItemHeight = 56;
|
|
22
22
|
let measured = false;
|
|
23
23
|
|
|
24
24
|
const overscan = 3;
|
|
@@ -43,7 +43,7 @@
|
|
|
43
43
|
scrollTop = (e.target as HTMLDivElement).scrollTop;
|
|
44
44
|
}
|
|
45
45
|
|
|
46
|
-
// --- Virtualization
|
|
46
|
+
// --- Virtualization ---
|
|
47
47
|
$: totalHeight = items.length * estimatedItemHeight;
|
|
48
48
|
|
|
49
49
|
$: startIndex = Math.max(
|
|
@@ -55,13 +55,11 @@
|
|
|
55
55
|
Math.ceil(viewportHeight / estimatedItemHeight) + overscan * 2;
|
|
56
56
|
|
|
57
57
|
$: endIndex = Math.min(items.length, startIndex + visibleCount);
|
|
58
|
-
|
|
59
58
|
$: visibleItems = items.slice(startIndex, endIndex);
|
|
60
59
|
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
? `${arrangement.gap}px`
|
|
60
|
+
function resolveGap(): string {
|
|
61
|
+
return verticalArrangement.type === "spaced"
|
|
62
|
+
? `${verticalArrangement.gap}px`
|
|
65
63
|
: "0px";
|
|
66
64
|
}
|
|
67
65
|
</script>
|
|
@@ -69,15 +67,17 @@
|
|
|
69
67
|
<div
|
|
70
68
|
bind:this={container}
|
|
71
69
|
on:scroll={onScroll}
|
|
70
|
+
class="compose-lazy-column"
|
|
72
71
|
style={`
|
|
73
|
-
overflow-y:auto;
|
|
74
|
-
|
|
72
|
+
overflow-y: auto;
|
|
73
|
+
overflow-x: hidden;
|
|
74
|
+
position: relative;
|
|
75
75
|
${modifier.toStyle()}
|
|
76
76
|
`}
|
|
77
77
|
>
|
|
78
|
-
<!--
|
|
78
|
+
<!-- Espacio total -->
|
|
79
79
|
<div style={`height:${totalHeight}px; position:relative;`}>
|
|
80
|
-
<!--
|
|
80
|
+
<!-- Ventana visible -->
|
|
81
81
|
<div
|
|
82
82
|
style={`
|
|
83
83
|
position:absolute;
|
|
@@ -88,7 +88,7 @@
|
|
|
88
88
|
display:flex;
|
|
89
89
|
flex-direction:column;
|
|
90
90
|
align-items:${horizontalAlignment};
|
|
91
|
-
gap:${resolveGap(
|
|
91
|
+
gap:${resolveGap()};
|
|
92
92
|
`}
|
|
93
93
|
>
|
|
94
94
|
{#each visibleItems as item, i}
|
|
@@ -1,71 +1,107 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
2
|
import { Modifier } from "../../core/modifier/Modifier";
|
|
3
|
+
import { onMount, tick } from "svelte";
|
|
3
4
|
import { Alignment } from "./Alignment";
|
|
4
5
|
import { Arrangement } from "./Arrangement";
|
|
5
6
|
import type { ArrangementValue } from "./Arrangement";
|
|
6
|
-
import type {
|
|
7
|
+
import type { HorizontalAlignment } from "./Alignment";
|
|
7
8
|
|
|
8
9
|
export let items: any[] = [];
|
|
9
10
|
export let modifier: Modifier = Modifier.empty();
|
|
10
11
|
|
|
11
|
-
export let
|
|
12
|
-
export let
|
|
12
|
+
export let horizontalAlignment: HorizontalAlignment = Alignment.Start;
|
|
13
|
+
export let verticalArrangement: ArrangementValue = Arrangement.Start;
|
|
13
14
|
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
export let horizontalSpacing: number | null = null;
|
|
15
|
+
let container: HTMLDivElement;
|
|
16
|
+
let probeItem: HTMLDivElement | null = null;
|
|
17
17
|
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
18
|
+
let scrollTop = 0;
|
|
19
|
+
let viewportHeight = 0;
|
|
20
|
+
|
|
21
|
+
let estimatedItemHeight = 56; // fallback Material
|
|
22
|
+
let measured = false;
|
|
23
|
+
|
|
24
|
+
const overscan = 3;
|
|
25
|
+
|
|
26
|
+
onMount(() => {
|
|
27
|
+
viewportHeight = container.clientHeight;
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
async function measure() {
|
|
31
|
+
await tick();
|
|
32
|
+
if (probeItem) {
|
|
33
|
+
estimatedItemHeight = probeItem.offsetHeight;
|
|
34
|
+
measured = true;
|
|
21
35
|
}
|
|
36
|
+
}
|
|
22
37
|
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
: "0px";
|
|
38
|
+
$: if (probeItem && !measured) {
|
|
39
|
+
measure();
|
|
26
40
|
}
|
|
27
41
|
|
|
28
|
-
function
|
|
29
|
-
|
|
42
|
+
function onScroll(e: Event) {
|
|
43
|
+
scrollTop = (e.target as HTMLDivElement).scrollTop;
|
|
30
44
|
}
|
|
31
45
|
|
|
32
|
-
|
|
33
|
-
|
|
46
|
+
// --- Virtualization math ---
|
|
47
|
+
$: totalHeight = items.length * estimatedItemHeight;
|
|
34
48
|
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
}
|
|
40
|
-
</script>
|
|
49
|
+
$: startIndex = Math.max(
|
|
50
|
+
0,
|
|
51
|
+
Math.floor(scrollTop / estimatedItemHeight) - overscan
|
|
52
|
+
);
|
|
41
53
|
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
style={`
|
|
45
|
-
display: flex;
|
|
46
|
-
flex-direction: row;
|
|
54
|
+
$: visibleCount =
|
|
55
|
+
Math.ceil(viewportHeight / estimatedItemHeight) + overscan * 2;
|
|
47
56
|
|
|
48
|
-
|
|
49
|
-
justify-content: ${horizontalArrangement.justifyContent};
|
|
50
|
-
gap: ${resolveGap()};
|
|
57
|
+
$: endIndex = Math.min(items.length, startIndex + visibleCount);
|
|
51
58
|
|
|
52
|
-
|
|
53
|
-
overflow-y: visible;
|
|
59
|
+
$: visibleItems = items.slice(startIndex, endIndex);
|
|
54
60
|
|
|
55
|
-
|
|
56
|
-
|
|
61
|
+
// --- Arrangement ---
|
|
62
|
+
function resolveGap(arrangement: ArrangementValue): string {
|
|
63
|
+
return arrangement.type === "spaced"
|
|
64
|
+
? `${arrangement.gap}px`
|
|
65
|
+
: "0px";
|
|
66
|
+
}
|
|
67
|
+
</script>
|
|
57
68
|
|
|
58
|
-
|
|
69
|
+
<div
|
|
70
|
+
bind:this={container}
|
|
71
|
+
on:scroll={onScroll}
|
|
72
|
+
style={`
|
|
73
|
+
overflow-y:auto;
|
|
74
|
+
position:relative;
|
|
59
75
|
${modifier.toStyle()}
|
|
60
76
|
`}
|
|
61
77
|
>
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
78
|
+
<!-- Total scroll space -->
|
|
79
|
+
<div style={`height:${totalHeight}px; position:relative;`}>
|
|
80
|
+
<!-- Visible window -->
|
|
81
|
+
<div
|
|
82
|
+
style={`
|
|
83
|
+
position:absolute;
|
|
84
|
+
top:${startIndex * estimatedItemHeight}px;
|
|
85
|
+
left:0;
|
|
86
|
+
right:0;
|
|
87
|
+
|
|
88
|
+
display:flex;
|
|
89
|
+
flex-direction:column;
|
|
90
|
+
align-items:${horizontalAlignment};
|
|
91
|
+
gap:${resolveGap(verticalArrangement)};
|
|
92
|
+
`}
|
|
93
|
+
>
|
|
94
|
+
{#each visibleItems as item, i}
|
|
95
|
+
{#if i === 0 && !measured}
|
|
96
|
+
<div bind:this={probeItem}>
|
|
97
|
+
<slot {item} />
|
|
98
|
+
</div>
|
|
99
|
+
{:else}
|
|
100
|
+
<div>
|
|
101
|
+
<slot {item} />
|
|
102
|
+
</div>
|
|
103
|
+
{/if}
|
|
104
|
+
{/each}
|
|
105
|
+
</div>
|
|
106
|
+
</div>
|
|
107
|
+
</div>
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Modifier } from "../../core/modifier/Modifier";
|
|
2
2
|
import type { ArrangementValue } from "./Arrangement";
|
|
3
|
-
import type {
|
|
3
|
+
import type { HorizontalAlignment } from "./Alignment";
|
|
4
4
|
interface $$__sveltets_2_IsomorphicComponent<Props extends Record<string, any> = any, Events extends Record<string, any> = any, Slots extends Record<string, any> = any, Exports = {}, Bindings = string> {
|
|
5
5
|
new (options: import('svelte').ComponentConstructorOptions<Props>): import('svelte').SvelteComponent<Props, Events, Slots> & {
|
|
6
6
|
$$bindings?: Bindings;
|
|
@@ -22,11 +22,8 @@ type $$__sveltets_2_PropsWithChildren<Props, Slots> = Props & (Slots extends {
|
|
|
22
22
|
declare const LazyRow: $$__sveltets_2_IsomorphicComponent<$$__sveltets_2_PropsWithChildren<{
|
|
23
23
|
items?: any[];
|
|
24
24
|
modifier?: Modifier;
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
scrollEnabled?: boolean;
|
|
28
|
-
hideScrollbar?: boolean;
|
|
29
|
-
horizontalSpacing?: number | null;
|
|
25
|
+
horizontalAlignment?: HorizontalAlignment;
|
|
26
|
+
verticalArrangement?: ArrangementValue;
|
|
30
27
|
}, {
|
|
31
28
|
default: {
|
|
32
29
|
item: any;
|
|
@@ -1,70 +1,50 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
2
|
import { Modifier } from "../../core/modifier/Modifier";
|
|
3
|
+
import { resolveBoxAlignment } from "./resolveAlignment";
|
|
4
|
+
import {Alignment, BoxAlignment} from "./Alignment";
|
|
3
5
|
|
|
4
6
|
export let modifier: Modifier = Modifier.empty();
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
export let contentPadding: number = 16;
|
|
8
|
-
|
|
9
|
-
// Control del FAB
|
|
10
|
-
export let fabAlignment:
|
|
11
|
-
| "bottom-end"
|
|
12
|
-
| "bottom-center"
|
|
13
|
-
| "bottom-start" = "bottom-end";
|
|
7
|
+
export let contentPadding = 16;
|
|
8
|
+
export let fabAlignment: BoxAlignment = Alignment.BottomEnd;
|
|
14
9
|
</script>
|
|
15
10
|
|
|
16
11
|
<div
|
|
12
|
+
class="compose-relative"
|
|
17
13
|
style={`
|
|
18
14
|
display: flex;
|
|
19
15
|
flex-direction: column;
|
|
20
|
-
height: 100%;
|
|
21
16
|
width: 100%;
|
|
22
|
-
|
|
17
|
+
height: 100%;
|
|
23
18
|
${modifier.toStyle()}
|
|
24
19
|
`}
|
|
25
20
|
>
|
|
26
|
-
<!-- Top
|
|
27
|
-
<
|
|
28
|
-
<slot name="topBar" />
|
|
29
|
-
</div>
|
|
21
|
+
<!-- Top bar -->
|
|
22
|
+
<slot name="topBar" />
|
|
30
23
|
|
|
31
24
|
<!-- Content -->
|
|
32
25
|
<div
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
position: relative;
|
|
36
|
-
padding: ${contentPadding}px;
|
|
37
|
-
overflow: auto;
|
|
38
|
-
`}
|
|
26
|
+
class="compose-scaffold-content"
|
|
27
|
+
style={`padding:${contentPadding}px;`}
|
|
39
28
|
>
|
|
40
29
|
<slot />
|
|
41
30
|
</div>
|
|
42
31
|
|
|
43
|
-
<!-- Bottom
|
|
44
|
-
<
|
|
45
|
-
<slot name="bottomBar" />
|
|
46
|
-
</div>
|
|
32
|
+
<!-- Bottom bar -->
|
|
33
|
+
<slot name="bottomBar" />
|
|
47
34
|
|
|
48
|
-
<!--
|
|
35
|
+
<!-- FAB overlay -->
|
|
49
36
|
<div
|
|
50
37
|
style={`
|
|
51
|
-
position:
|
|
52
|
-
|
|
53
|
-
|
|
38
|
+
position:absolute;
|
|
39
|
+
inset:0;
|
|
40
|
+
pointer-events:none;
|
|
54
41
|
`}
|
|
55
42
|
>
|
|
56
43
|
<div
|
|
57
44
|
style={`
|
|
58
|
-
|
|
59
|
-
pointer-events:
|
|
60
|
-
|
|
61
|
-
${
|
|
62
|
-
fabAlignment === "bottom-end"
|
|
63
|
-
? "right: 16px; bottom: 16px;"
|
|
64
|
-
: fabAlignment === "bottom-center"
|
|
65
|
-
? "left: 50%; transform: translateX(-50%); bottom: 16px;"
|
|
66
|
-
: "left: 16px; bottom: 16px;"
|
|
67
|
-
}
|
|
45
|
+
${resolveBoxAlignment(fabAlignment)}
|
|
46
|
+
pointer-events:auto;
|
|
47
|
+
margin:16px;
|
|
68
48
|
`}
|
|
69
49
|
>
|
|
70
50
|
<slot name="floatingActionButton" />
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { Modifier } from "../../core/modifier/Modifier";
|
|
2
|
+
import { BoxAlignment } from "./Alignment";
|
|
2
3
|
interface $$__sveltets_2_IsomorphicComponent<Props extends Record<string, any> = any, Events extends Record<string, any> = any, Slots extends Record<string, any> = any, Exports = {}, Bindings = string> {
|
|
3
4
|
new (options: import('svelte').ComponentConstructorOptions<Props>): import('svelte').SvelteComponent<Props, Events, Slots> & {
|
|
4
5
|
$$bindings?: Bindings;
|
|
@@ -20,7 +21,7 @@ type $$__sveltets_2_PropsWithChildren<Props, Slots> = Props & (Slots extends {
|
|
|
20
21
|
declare const Scaffold: $$__sveltets_2_IsomorphicComponent<$$__sveltets_2_PropsWithChildren<{
|
|
21
22
|
modifier?: Modifier;
|
|
22
23
|
contentPadding?: number;
|
|
23
|
-
fabAlignment?:
|
|
24
|
+
fabAlignment?: BoxAlignment;
|
|
24
25
|
}, {
|
|
25
26
|
topBar: {};
|
|
26
27
|
default: {};
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
/* compose-svelted baseline.css */
|
|
2
|
+
|
|
3
|
+
/* 1. Modelo de caja consistente */
|
|
4
|
+
*, *::before, *::after {
|
|
5
|
+
box-sizing: border-box;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
/* 2. Root layout estable */
|
|
9
|
+
html, body {
|
|
10
|
+
margin: 0;
|
|
11
|
+
padding: 0;
|
|
12
|
+
width: 100%;
|
|
13
|
+
height: 100%;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
/* 3. Host de la app */
|
|
17
|
+
#app, body > div {
|
|
18
|
+
width: 100%;
|
|
19
|
+
height: 100%;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/* 4. Prevención de colapso en flex */
|
|
23
|
+
* {
|
|
24
|
+
min-width: 0;
|
|
25
|
+
min-height: 0;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/* 5. Soporte para absolute alignment */
|
|
29
|
+
.compose-relative {
|
|
30
|
+
position: relative;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/* 6. Clickable base */
|
|
34
|
+
.compose-clickable {
|
|
35
|
+
cursor: pointer;
|
|
36
|
+
user-select: none;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/* 7. Evitar interferencia de estilos externos */
|
|
40
|
+
img, svg, video, canvas {
|
|
41
|
+
display: block;
|
|
42
|
+
max-width: 100%;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
.compose-lazy-row,
|
|
46
|
+
.compose-lazy-column {
|
|
47
|
+
min-width: 0;
|
|
48
|
+
min-height: 0;
|
|
49
|
+
}
|
package/dist/index.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@danielito1996/compose-svelted",
|
|
3
|
-
"version": "0.2.7-
|
|
3
|
+
"version": "0.2.7-alpha03",
|
|
4
4
|
"description": "Compose-like UI toolkit for Svelte, inspired by Jetpack Compose",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -18,7 +18,8 @@
|
|
|
18
18
|
"types": "./dist/index.d.ts",
|
|
19
19
|
"import": "./dist/index.js",
|
|
20
20
|
"svelte": "./dist/index.js"
|
|
21
|
-
}
|
|
21
|
+
},
|
|
22
|
+
"./baseline.css": "./dist/core/styles/baseline.css"
|
|
22
23
|
},
|
|
23
24
|
"files": [
|
|
24
25
|
"dist"
|