@hkdigital/lib-sveltekit 0.1.16 → 0.1.18
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/buttons/button/Button.svelte +1 -1
- package/dist/components/buttons/button/Button.svelte.d.ts +2 -2
- package/dist/components/debug/debug-panel-design-scaling/DebugPanelDesignScaling.svelte +146 -0
- package/dist/components/debug/debug-panel-design-scaling/DebugPanelDesignScaling.svelte.d.ts +6 -0
- package/dist/components/debug/index.d.ts +1 -0
- package/dist/components/debug/index.js +1 -0
- package/dist/components/layout/HkAppLayout.svelte +3 -3
- package/dist/components/layout/game-box/GameBox.svelte +167 -0
- package/dist/components/layout/game-box/GameBox.svelte.d.ts +80 -0
- package/dist/components/layout/grid-layers/GridLayers.svelte +167 -0
- package/dist/components/layout/{HkGridLayers.svelte.d.ts → grid-layers/GridLayers.svelte.d.ts} +21 -21
- package/dist/components/layout/index.d.ts +3 -1
- package/dist/components/layout/index.js +3 -1
- package/dist/util/design-system/layout/scaling.d.ts +54 -0
- package/dist/util/design-system/layout/scaling.js +131 -0
- package/package.json +1 -1
- package/dist/components/boxes/game-box/GameBox.svelte +0 -112
- package/dist/components/boxes/game-box/GameBox.svelte.d.ts +0 -28
- package/dist/components/boxes/index.d.ts +0 -2
- package/dist/components/boxes/index.js +0 -2
- package/dist/components/layout/HkGridLayers.svelte +0 -82
- /package/dist/components/{boxes → layout}/game-box/gamebox.util.d.ts +0 -0
- /package/dist/components/{boxes → layout}/game-box/gamebox.util.js +0 -0
- /package/dist/components/{boxes → layout}/virtual-viewport/VirtualViewport.svelte +0 -0
- /package/dist/components/{boxes → layout}/virtual-viewport/VirtualViewport.svelte.d.ts +0 -0
@@ -7,7 +7,7 @@ type Button = {
|
|
7
7
|
bg?: string;
|
8
8
|
classes?: string;
|
9
9
|
type?: string;
|
10
|
-
role?: "primary" | "secondary";
|
10
|
+
role?: "custom" | "primary" | "secondary" | "tertiary";
|
11
11
|
size?: "sm" | "md" | "lg";
|
12
12
|
variant?: string;
|
13
13
|
active?: boolean;
|
@@ -26,7 +26,7 @@ declare const Button: import("svelte").Component<{
|
|
26
26
|
bg?: string;
|
27
27
|
classes?: string;
|
28
28
|
type?: string;
|
29
|
-
role?: "primary" | "secondary";
|
29
|
+
role?: "primary" | "secondary" | "tertiary" | "custom";
|
30
30
|
size?: "sm" | "md" | "lg";
|
31
31
|
variant?: string;
|
32
32
|
active?: boolean;
|
@@ -0,0 +1,146 @@
|
|
1
|
+
<script>
|
2
|
+
import { onMount } from 'svelte';
|
3
|
+
import { DESIGN, CLAMPING } from '../../../design/design-config.js';
|
4
|
+
import {
|
5
|
+
enableScalingUI,
|
6
|
+
getAllRootScalingVars
|
7
|
+
} from '../../../util/design-system/index.js';
|
8
|
+
|
9
|
+
/**
|
10
|
+
* Holds the current scaling values for the debug panel
|
11
|
+
* @type {Object}
|
12
|
+
*/
|
13
|
+
let scalingValues = $state({
|
14
|
+
scaleW: 0,
|
15
|
+
scaleH: 0,
|
16
|
+
scaleViewport: 0,
|
17
|
+
scaleUI: 0,
|
18
|
+
scaleTextBase: 0,
|
19
|
+
scaleTextHeading: 0,
|
20
|
+
scaleTextUI: 0
|
21
|
+
});
|
22
|
+
|
23
|
+
/**
|
24
|
+
* Controls visibility of the debug panel
|
25
|
+
*/
|
26
|
+
let showDebugPanel = $state(false);
|
27
|
+
|
28
|
+
/**
|
29
|
+
* Updates scaling values for the debug panel
|
30
|
+
*/
|
31
|
+
function updateDebugValues() {
|
32
|
+
// Get scaling values
|
33
|
+
scalingValues = getAllRootScalingVars();
|
34
|
+
|
35
|
+
// Update window size display if in browser context
|
36
|
+
if (typeof window !== 'undefined') {
|
37
|
+
const windowSizeElement = document.getElementById('window-size');
|
38
|
+
if (windowSizeElement) {
|
39
|
+
windowSizeElement.textContent = `${window.innerWidth}×${window.innerHeight}px`;
|
40
|
+
}
|
41
|
+
}
|
42
|
+
}
|
43
|
+
|
44
|
+
onMount(() => {
|
45
|
+
// Initialize the design scaling system
|
46
|
+
//const cleanup = () => {};
|
47
|
+
const cleanup = enableScalingUI(DESIGN, CLAMPING);
|
48
|
+
|
49
|
+
// Update debug values initially
|
50
|
+
updateDebugValues();
|
51
|
+
|
52
|
+
// Set up event listener for updating debug values on resize
|
53
|
+
window.addEventListener('resize', updateDebugValues);
|
54
|
+
|
55
|
+
// Return combined cleanup function
|
56
|
+
return () => {
|
57
|
+
cleanup();
|
58
|
+
window.removeEventListener('resize', updateDebugValues);
|
59
|
+
};
|
60
|
+
});
|
61
|
+
|
62
|
+
/**
|
63
|
+
* Toggle debug panel visibility
|
64
|
+
*/
|
65
|
+
function toggleDebugPanel() {
|
66
|
+
showDebugPanel = !showDebugPanel;
|
67
|
+
}
|
68
|
+
|
69
|
+
/**
|
70
|
+
* Format a number to 2 decimal places
|
71
|
+
* @param {number} value - The number to format
|
72
|
+
* @returns {string} Formatted number
|
73
|
+
*/
|
74
|
+
function formatNumber(value) {
|
75
|
+
return value.toFixed(2);
|
76
|
+
}
|
77
|
+
</script>
|
78
|
+
|
79
|
+
<!-- Debug Panel -->
|
80
|
+
{#if showDebugPanel}
|
81
|
+
<div
|
82
|
+
class="fixed bottom-0 right-0 bg-black bg-opacity-75 text-white p-2 text-ui-md z-50 font-mono"
|
83
|
+
>
|
84
|
+
<div class="flex justify-between items-center mb-1">
|
85
|
+
<h3 class="font-bold">Design System Scaling</h3>
|
86
|
+
<button
|
87
|
+
onclick={toggleDebugPanel}
|
88
|
+
class="ml-2 px-1.5 bg-gray-700 hover:bg-gray-600 rounded"
|
89
|
+
>
|
90
|
+
×
|
91
|
+
</button>
|
92
|
+
</div>
|
93
|
+
<div class="grid grid-cols-2 gap-x-2 gap-y-0.5">
|
94
|
+
<div class="text-gray-400">Design Width:</div>
|
95
|
+
<div>{DESIGN.width}px</div>
|
96
|
+
|
97
|
+
<div class="text-gray-400">Design Height:</div>
|
98
|
+
<div>{DESIGN.height}px</div>
|
99
|
+
|
100
|
+
<div class="text-gray-400">Window:</div>
|
101
|
+
<div id="window-size">...</div>
|
102
|
+
|
103
|
+
<div class="text-gray-400">Scale W:</div>
|
104
|
+
<div>{formatNumber(scalingValues.scaleW)}</div>
|
105
|
+
|
106
|
+
<div class="text-gray-400">Scale H:</div>
|
107
|
+
<div>{formatNumber(scalingValues.scaleH)}</div>
|
108
|
+
|
109
|
+
<div class="text-gray-400">Viewport:</div>
|
110
|
+
<div>{formatNumber(scalingValues.scaleViewport)}</div>
|
111
|
+
|
112
|
+
<div class="text-gray-400">UI:</div>
|
113
|
+
<div>{formatNumber(scalingValues.scaleUI)}</div>
|
114
|
+
|
115
|
+
<div class="text-gray-400">Text Content:</div>
|
116
|
+
<div>{formatNumber(scalingValues.scaleTextBase)}</div>
|
117
|
+
|
118
|
+
<div class="text-gray-400">Text Heading:</div>
|
119
|
+
<div>{formatNumber(scalingValues.scaleTextHeading)}</div>
|
120
|
+
|
121
|
+
<div class="text-gray-400">Text UI:</div>
|
122
|
+
<div>{formatNumber(scalingValues.scaleTextUI)}</div>
|
123
|
+
</div>
|
124
|
+
|
125
|
+
<div class="mt-1 pt-1 border-t border-gray-600 text-gray-400">
|
126
|
+
<div>Clamping:</div>
|
127
|
+
<div class="grid grid-cols-3 text-2xs">
|
128
|
+
<div>UI: {CLAMPING.ui.min} - {CLAMPING.ui.max}</div>
|
129
|
+
<div>
|
130
|
+
Content: {CLAMPING.textBase.min} - {CLAMPING.textBase.max}
|
131
|
+
</div>
|
132
|
+
<div>
|
133
|
+
Heading: {CLAMPING.textHeading.min} - {CLAMPING.textHeading.max}
|
134
|
+
</div>
|
135
|
+
</div>
|
136
|
+
</div>
|
137
|
+
</div>
|
138
|
+
{:else}
|
139
|
+
<!-- Debug Panel Toggle Button -->
|
140
|
+
<button
|
141
|
+
onclick={toggleDebugPanel}
|
142
|
+
class="fixed bottom-0 right-0 bg-black bg-opacity-75 text-white p-16ut py-8ut text-ui-md z-50 font-mono hover:bg-opacity-90"
|
143
|
+
>
|
144
|
+
Show Debug
|
145
|
+
</button>
|
146
|
+
{/if}
|
@@ -0,0 +1,6 @@
|
|
1
|
+
export default DebugPanelDesignScaling;
|
2
|
+
type DebugPanelDesignScaling = {
|
3
|
+
$on?(type: string, callback: (e: any) => void): () => void;
|
4
|
+
$set?(props: Partial<Record<string, never>>): void;
|
5
|
+
};
|
6
|
+
declare const DebugPanelDesignScaling: import("svelte").Component<Record<string, never>, {}, "">;
|
@@ -0,0 +1 @@
|
|
1
|
+
export { default as DebugPanelDesignScaling } from "./debug-panel-design-scaling/DebugPanelDesignScaling.svelte";
|
@@ -0,0 +1 @@
|
|
1
|
+
export { default as DebugPanelDesignScaling } from './debug-panel-design-scaling/DebugPanelDesignScaling.svelte';
|
@@ -241,11 +241,11 @@
|
|
241
241
|
grid-area: 1 / 1 / 2 / 2; /* row-start, col-start, row-end, col-end */
|
242
242
|
}
|
243
243
|
|
244
|
-
|
245
|
-
/*
|
244
|
+
/*
|
246
245
|
* Shift contents of page to the left when scrollbar appears,
|
247
246
|
* so content like tab bars stay centered
|
248
247
|
*/
|
248
|
+
/*:global(html:not(.no-scrollbar-shift-fix)) {
|
249
249
|
padding-left: calc(100vw - 100%);
|
250
|
-
}
|
250
|
+
}*/
|
251
251
|
</style>
|
@@ -0,0 +1,167 @@
|
|
1
|
+
<script>
|
2
|
+
import { onMount } from 'svelte';
|
3
|
+
import {
|
4
|
+
getGameWidthOnLandscape,
|
5
|
+
getGameWidthOnPortrait
|
6
|
+
} from './gamebox.util.js';
|
7
|
+
import { enableContainerScaling } from '../../../util/design-system/index.js';
|
8
|
+
|
9
|
+
/**
|
10
|
+
* @type {{
|
11
|
+
* base?: string,
|
12
|
+
* bg?: string,
|
13
|
+
* classes?: string,
|
14
|
+
* style?: string,
|
15
|
+
* aspectOnLandscape?: number,
|
16
|
+
* aspectOnPortrait?: number,
|
17
|
+
* enableScaling?: boolean,
|
18
|
+
* designLandscape?: {width: number, height: number},
|
19
|
+
* designPortrait?: {width: number, height: number},
|
20
|
+
* clamping?: {
|
21
|
+
* ui: {min: number, max: number},
|
22
|
+
* textBase: {min: number, max: number},
|
23
|
+
* textHeading: {min: number, max: number},
|
24
|
+
* textUi: {min: number, max: number}
|
25
|
+
* },
|
26
|
+
* snippetLandscape?: import('svelte').Snippet,
|
27
|
+
* snippetPortrait?: import('svelte').Snippet,
|
28
|
+
* [attr: string]: any
|
29
|
+
* }}
|
30
|
+
*/
|
31
|
+
const {
|
32
|
+
// > Style
|
33
|
+
base = '',
|
34
|
+
bg = '',
|
35
|
+
classes = '',
|
36
|
+
style = '',
|
37
|
+
|
38
|
+
// > Functional properties
|
39
|
+
aspectOnLandscape,
|
40
|
+
aspectOnPortrait,
|
41
|
+
|
42
|
+
// > Scaling options
|
43
|
+
enableScaling = false,
|
44
|
+
designLandscape = { width: 1920, height: 1080 },
|
45
|
+
designPortrait = { width: 1080, height: 1920 },
|
46
|
+
clamping = {
|
47
|
+
ui: { min: 0.3, max: 2 },
|
48
|
+
textBase: { min: 0.75, max: 1.5 },
|
49
|
+
textHeading: { min: 0.75, max: 2.25 },
|
50
|
+
textUi: { min: 0.5, max: 1.25 }
|
51
|
+
},
|
52
|
+
|
53
|
+
// > Snippets
|
54
|
+
snippetLandscape,
|
55
|
+
snippetPortrait
|
56
|
+
} = $props();
|
57
|
+
|
58
|
+
// > Game dimensions and state
|
59
|
+
let windowWidth = $state();
|
60
|
+
let windowHeight = $state();
|
61
|
+
let gameWidth = $state();
|
62
|
+
let gameHeight = $state();
|
63
|
+
let isLandscape = $derived(windowWidth > windowHeight);
|
64
|
+
|
65
|
+
// Game container reference
|
66
|
+
let gameContainer = $state();
|
67
|
+
|
68
|
+
// Update game dimensions based on window size and orientation
|
69
|
+
$effect(() => {
|
70
|
+
if (!windowWidth || !windowHeight) return;
|
71
|
+
|
72
|
+
let gameAspect;
|
73
|
+
|
74
|
+
if (windowWidth > windowHeight) {
|
75
|
+
gameWidth = getGameWidthOnLandscape({
|
76
|
+
windowWidth,
|
77
|
+
windowHeight,
|
78
|
+
aspectOnLandscape
|
79
|
+
});
|
80
|
+
gameAspect = aspectOnLandscape;
|
81
|
+
} else {
|
82
|
+
gameWidth = getGameWidthOnPortrait({
|
83
|
+
windowWidth,
|
84
|
+
windowHeight,
|
85
|
+
aspectOnPortrait
|
86
|
+
});
|
87
|
+
gameAspect = aspectOnPortrait;
|
88
|
+
}
|
89
|
+
|
90
|
+
if (gameAspect) {
|
91
|
+
gameHeight = gameWidth / gameAspect;
|
92
|
+
} else {
|
93
|
+
gameHeight = windowHeight;
|
94
|
+
}
|
95
|
+
});
|
96
|
+
|
97
|
+
// Set up scaling if enabled, with orientation awareness
|
98
|
+
$effect(() => {
|
99
|
+
if (!enableScaling || !gameContainer || !gameWidth || !gameHeight) {
|
100
|
+
return () => {}; // No-op cleanup if scaling not enabled or required elements missing
|
101
|
+
}
|
102
|
+
|
103
|
+
// Select the appropriate design based on orientation
|
104
|
+
const activeDesign = isLandscape ? designLandscape : designPortrait;
|
105
|
+
|
106
|
+
// Log to help debug
|
107
|
+
console.debug(
|
108
|
+
`GameBox scaling [${isLandscape ? 'landscape' : 'portrait'}]:`,
|
109
|
+
`game: ${gameWidth}x${gameHeight}`,
|
110
|
+
`design: ${activeDesign.width}x${activeDesign.height}`
|
111
|
+
);
|
112
|
+
|
113
|
+
// Apply scaling with the current design based on orientation
|
114
|
+
return enableContainerScaling({
|
115
|
+
container: gameContainer,
|
116
|
+
design: activeDesign,
|
117
|
+
clamping,
|
118
|
+
getDimensions: () => ({
|
119
|
+
width: gameWidth,
|
120
|
+
height: gameHeight
|
121
|
+
})
|
122
|
+
});
|
123
|
+
});
|
124
|
+
|
125
|
+
onMount(() => {
|
126
|
+
const gameBoxNoScroll = 'game-box-no-scroll';
|
127
|
+
const html = document.documentElement;
|
128
|
+
html.classList.add(gameBoxNoScroll);
|
129
|
+
|
130
|
+
return () => {
|
131
|
+
html.classList.remove(gameBoxNoScroll);
|
132
|
+
};
|
133
|
+
});
|
134
|
+
</script>
|
135
|
+
|
136
|
+
<svelte:window bind:innerWidth={windowWidth} bind:innerHeight={windowHeight} />
|
137
|
+
|
138
|
+
{#if gameHeight}
|
139
|
+
<div
|
140
|
+
data-component="game-box"
|
141
|
+
data-orientation={isLandscape ? 'landscape' : 'portrait'}
|
142
|
+
bind:this={gameContainer}
|
143
|
+
class="{base} {bg} {classes}"
|
144
|
+
style:width="{gameWidth}px"
|
145
|
+
style:height="{gameHeight}px"
|
146
|
+
style:--game-width={gameWidth}
|
147
|
+
style:--game-height={gameHeight}
|
148
|
+
{style}
|
149
|
+
>
|
150
|
+
{#if isLandscape}
|
151
|
+
{@render snippetLandscape()}
|
152
|
+
{:else}
|
153
|
+
{@render snippetPortrait()}
|
154
|
+
{/if}
|
155
|
+
</div>
|
156
|
+
{/if}
|
157
|
+
|
158
|
+
<style>
|
159
|
+
:global(html.game-box-no-scroll) {
|
160
|
+
overflow: clip;
|
161
|
+
scrollbar-width: none; /* Firefox */
|
162
|
+
-ms-overflow-style: none; /* IE and Edge */
|
163
|
+
}
|
164
|
+
:global(html.game-box-no-scroll::-webkit-scrollbar) {
|
165
|
+
display: none;
|
166
|
+
}
|
167
|
+
</style>
|
@@ -0,0 +1,80 @@
|
|
1
|
+
export default GameBox;
|
2
|
+
type GameBox = {
|
3
|
+
$on?(type: string, callback: (e: any) => void): () => void;
|
4
|
+
$set?(props: Partial<{
|
5
|
+
[attr: string]: any;
|
6
|
+
base?: string;
|
7
|
+
bg?: string;
|
8
|
+
classes?: string;
|
9
|
+
style?: string;
|
10
|
+
aspectOnLandscape?: number;
|
11
|
+
aspectOnPortrait?: number;
|
12
|
+
enableScaling?: boolean;
|
13
|
+
designLandscape?: {
|
14
|
+
width: number;
|
15
|
+
height: number;
|
16
|
+
};
|
17
|
+
designPortrait?: {
|
18
|
+
width: number;
|
19
|
+
height: number;
|
20
|
+
};
|
21
|
+
clamping?: {
|
22
|
+
ui: {
|
23
|
+
min: number;
|
24
|
+
max: number;
|
25
|
+
};
|
26
|
+
textBase: {
|
27
|
+
min: number;
|
28
|
+
max: number;
|
29
|
+
};
|
30
|
+
textHeading: {
|
31
|
+
min: number;
|
32
|
+
max: number;
|
33
|
+
};
|
34
|
+
textUi: {
|
35
|
+
min: number;
|
36
|
+
max: number;
|
37
|
+
};
|
38
|
+
};
|
39
|
+
snippetLandscape?: Snippet<[]>;
|
40
|
+
snippetPortrait?: Snippet<[]>;
|
41
|
+
}>): void;
|
42
|
+
};
|
43
|
+
declare const GameBox: import("svelte").Component<{
|
44
|
+
[attr: string]: any;
|
45
|
+
base?: string;
|
46
|
+
bg?: string;
|
47
|
+
classes?: string;
|
48
|
+
style?: string;
|
49
|
+
aspectOnLandscape?: number;
|
50
|
+
aspectOnPortrait?: number;
|
51
|
+
enableScaling?: boolean;
|
52
|
+
designLandscape?: {
|
53
|
+
width: number;
|
54
|
+
height: number;
|
55
|
+
};
|
56
|
+
designPortrait?: {
|
57
|
+
width: number;
|
58
|
+
height: number;
|
59
|
+
};
|
60
|
+
clamping?: {
|
61
|
+
ui: {
|
62
|
+
min: number;
|
63
|
+
max: number;
|
64
|
+
};
|
65
|
+
textBase: {
|
66
|
+
min: number;
|
67
|
+
max: number;
|
68
|
+
};
|
69
|
+
textHeading: {
|
70
|
+
min: number;
|
71
|
+
max: number;
|
72
|
+
};
|
73
|
+
textUi: {
|
74
|
+
min: number;
|
75
|
+
max: number;
|
76
|
+
};
|
77
|
+
};
|
78
|
+
snippetLandscape?: import("svelte").Snippet;
|
79
|
+
snippetPortrait?: import("svelte").Snippet;
|
80
|
+
}, {}, "">;
|
@@ -0,0 +1,167 @@
|
|
1
|
+
<script>
|
2
|
+
/**
|
3
|
+
* Grid Layers Component
|
4
|
+
*
|
5
|
+
* A component that creates a single-cell grid where all children exist
|
6
|
+
* in the same grid cell, allowing them to be positioned independently
|
7
|
+
* and stacked on top of each other. Perfect for complex layouts like
|
8
|
+
* overlaying text on images, card stacks, positioning UI elements, etc.
|
9
|
+
*
|
10
|
+
* Each child can use grid positioning properties (justify-self-*, self-*)
|
11
|
+
* for precise placement. Children can control stacking order with z-index.
|
12
|
+
*
|
13
|
+
* @example Basic usage with 9-position grid
|
14
|
+
* ```html
|
15
|
+
* <GridLayers classes="border w-[500px] h-[500px]">
|
16
|
+
* <!-- Top Row -->
|
17
|
+
* <div class="justify-self-start self-start">
|
18
|
+
* <div class="bg-blue-500 w-[100px] h-[100px]">
|
19
|
+
* Top Left
|
20
|
+
* </div>
|
21
|
+
* </div>
|
22
|
+
* <div class="justify-self-center self-start">
|
23
|
+
* <div class="bg-blue-300 w-[100px] h-[100px]">
|
24
|
+
* Top Center
|
25
|
+
* </div>
|
26
|
+
* </div>
|
27
|
+
* <div class="justify-self-end self-start">
|
28
|
+
* <div class="bg-blue-500 w-[100px] h-[100px]">
|
29
|
+
* Top Right
|
30
|
+
* </div>
|
31
|
+
* </div>
|
32
|
+
*
|
33
|
+
* <!-- Middle Row -->
|
34
|
+
* <div class="justify-self-start self-center">
|
35
|
+
* <div class="bg-green-500 w-[100px] h-[100px]">
|
36
|
+
* Middle Left
|
37
|
+
* </div>
|
38
|
+
* </div>
|
39
|
+
* <div class="justify-self-center self-center">
|
40
|
+
* <div class="bg-green-300 w-[100px] h-[100px]">
|
41
|
+
* Middle Center
|
42
|
+
* </div>
|
43
|
+
* </div>
|
44
|
+
* <div class="justify-self-end self-center">
|
45
|
+
* <div class="bg-green-500 w-[100px] h-[100px]">
|
46
|
+
* Middle Right
|
47
|
+
* </div>
|
48
|
+
* </div>
|
49
|
+
*
|
50
|
+
* <!-- Bottom Row -->
|
51
|
+
* <div class="justify-self-start self-end">
|
52
|
+
* <div class="bg-red-500 w-[100px] h-[100px]">
|
53
|
+
* Bottom Left
|
54
|
+
* </div>
|
55
|
+
* </div>
|
56
|
+
* <div class="justify-self-center self-end">
|
57
|
+
* <div class="bg-red-300 w-[100px] h-[100px]">
|
58
|
+
* Bottom Center
|
59
|
+
* </div>
|
60
|
+
* </div>
|
61
|
+
* <div class="justify-self-end self-end">
|
62
|
+
* <div class="bg-red-500 w-[100px] h-[100px]">
|
63
|
+
* Bottom Right
|
64
|
+
* </div>
|
65
|
+
* </div>
|
66
|
+
* </GridLayers>
|
67
|
+
* ```
|
68
|
+
*
|
69
|
+
* @example Text over image
|
70
|
+
* ```html
|
71
|
+
* <GridLayers classes="w-full h-[300px]">
|
72
|
+
* <!-- Background image layer -->
|
73
|
+
* <div class="justify-self-stretch self-stretch z-0">
|
74
|
+
* <img
|
75
|
+
* src="/images/landscape.jpg"
|
76
|
+
* alt="Landscape"
|
77
|
+
* class="w-full h-full object-cover"
|
78
|
+
* />
|
79
|
+
* </div>
|
80
|
+
*
|
81
|
+
* <!-- Text overlay layer -->
|
82
|
+
* <div class="justify-self-center self-center z-10">
|
83
|
+
* <div class="bg-black/50 p-16up text-white
|
84
|
+
* font-ui rounded-md">
|
85
|
+
* <h2 class="text-2xl">Explore Nature</h2>
|
86
|
+
* <p>Discover the beauty of the outdoors</p>
|
87
|
+
* </div>
|
88
|
+
* </div>
|
89
|
+
* </GridLayers>
|
90
|
+
* ```
|
91
|
+
*/
|
92
|
+
|
93
|
+
/**
|
94
|
+
* @type {{
|
95
|
+
* base?: string,
|
96
|
+
* bg?: string,
|
97
|
+
* padding?: string,
|
98
|
+
* margin?: string,
|
99
|
+
* height?: string,
|
100
|
+
* classes?: string,
|
101
|
+
* style?: string,
|
102
|
+
* cellBase?: string,
|
103
|
+
* cellBg?: string,
|
104
|
+
* cellPadding?: string,
|
105
|
+
* cellMargin?: string,
|
106
|
+
* cellClasses?: string,
|
107
|
+
* cellStyle?: string,
|
108
|
+
* children: import('svelte').Snippet,
|
109
|
+
* cellAttrs?: { [attr: string]: * },
|
110
|
+
* [attr: string]: any
|
111
|
+
* }}
|
112
|
+
*/
|
113
|
+
const {
|
114
|
+
// Style
|
115
|
+
base,
|
116
|
+
bg,
|
117
|
+
padding,
|
118
|
+
margin,
|
119
|
+
height,
|
120
|
+
classes,
|
121
|
+
style,
|
122
|
+
cellBase,
|
123
|
+
cellBg,
|
124
|
+
cellPadding,
|
125
|
+
cellMargin,
|
126
|
+
cellClasses,
|
127
|
+
cellStyle,
|
128
|
+
|
129
|
+
cellAttrs,
|
130
|
+
|
131
|
+
// Snippets
|
132
|
+
children,
|
133
|
+
|
134
|
+
// Attributes
|
135
|
+
...attrs
|
136
|
+
} = $props();
|
137
|
+
</script>
|
138
|
+
|
139
|
+
<div
|
140
|
+
data-component="grid-layers"
|
141
|
+
class="relative {base} {bg} {height} {classes} {margin} {padding}"
|
142
|
+
{style}
|
143
|
+
{...attrs}
|
144
|
+
>
|
145
|
+
<div
|
146
|
+
data-section="layer"
|
147
|
+
class="absolute inset-0 grid {cellBase} {cellBg} {cellPadding} {cellMargin} {cellClasses}"
|
148
|
+
style={cellStyle}
|
149
|
+
>
|
150
|
+
{@render children()}
|
151
|
+
</div>
|
152
|
+
</div>
|
153
|
+
|
154
|
+
<style>
|
155
|
+
/* All children of the layer share the same grid area
|
156
|
+
but aren't absolutely positioned */
|
157
|
+
[data-section='layer'] {
|
158
|
+
grid-template-columns: 1fr;
|
159
|
+
grid-template-rows: 1fr;
|
160
|
+
}
|
161
|
+
|
162
|
+
[data-section='layer'] > :global(*) {
|
163
|
+
grid-column: 1;
|
164
|
+
grid-row: 1;
|
165
|
+
z-index: 0; /* Base z-index to allow explicit stacking order */
|
166
|
+
}
|
167
|
+
</style>
|
package/dist/components/layout/{HkGridLayers.svelte.d.ts → grid-layers/GridLayers.svelte.d.ts}
RENAMED
@@ -1,7 +1,8 @@
|
|
1
|
-
export default
|
2
|
-
type
|
1
|
+
export default GridLayers;
|
2
|
+
type GridLayers = {
|
3
3
|
$on?(type: string, callback: (e: any) => void): () => void;
|
4
4
|
$set?(props: Partial<{
|
5
|
+
[attr: string]: any;
|
5
6
|
base?: string;
|
6
7
|
bg?: string;
|
7
8
|
padding?: string;
|
@@ -9,20 +10,20 @@ type HkGridLayers = {
|
|
9
10
|
height?: string;
|
10
11
|
classes?: string;
|
11
12
|
style?: string;
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
13
|
+
cellBase?: string;
|
14
|
+
cellBg?: string;
|
15
|
+
cellPadding?: string;
|
16
|
+
cellMargin?: string;
|
17
|
+
cellClasses?: string;
|
18
|
+
cellStyle?: string;
|
19
|
+
children: Snippet<[]>;
|
20
|
+
cellAttrs?: {
|
18
21
|
[attr: string]: any;
|
19
22
|
};
|
20
|
-
children: Snippet<[]>;
|
21
|
-
} & {
|
22
|
-
[attr: string]: any;
|
23
23
|
}>): void;
|
24
24
|
};
|
25
|
-
declare const
|
25
|
+
declare const GridLayers: import("svelte").Component<{
|
26
|
+
[attr: string]: any;
|
26
27
|
base?: string;
|
27
28
|
bg?: string;
|
28
29
|
padding?: string;
|
@@ -30,15 +31,14 @@ declare const HkGridLayers: import("svelte").Component<{
|
|
30
31
|
height?: string;
|
31
32
|
classes?: string;
|
32
33
|
style?: string;
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
34
|
+
cellBase?: string;
|
35
|
+
cellBg?: string;
|
36
|
+
cellPadding?: string;
|
37
|
+
cellMargin?: string;
|
38
|
+
cellClasses?: string;
|
39
|
+
cellStyle?: string;
|
40
|
+
children: import("svelte").Snippet;
|
41
|
+
cellAttrs?: {
|
39
42
|
[attr: string]: any;
|
40
43
|
};
|
41
|
-
children: import("svelte").Snippet;
|
42
|
-
} & {
|
43
|
-
[attr: string]: any;
|
44
44
|
}, {}, "">;
|
@@ -1,3 +1,5 @@
|
|
1
1
|
export { default as HkAppLayout } from "./HkAppLayout.svelte";
|
2
|
-
export { default as
|
2
|
+
export { default as GameBox } from "./game-box/GameBox.svelte";
|
3
|
+
export { default as GridLayers } from "./grid-layers/GridLayers.svelte";
|
4
|
+
export { default as VirtualViewport } from "./virtual-viewport/VirtualViewport.svelte";
|
3
5
|
export { createOrGetState as createOrGetAppLayoutState, createState as createAppLayoutState, getState as getAppLayoutState } from "./HkAppLayout.state.svelte.js";
|
@@ -6,4 +6,6 @@ export {
|
|
6
6
|
|
7
7
|
export { default as HkAppLayout } from './HkAppLayout.svelte';
|
8
8
|
|
9
|
-
export { default as
|
9
|
+
export { default as GameBox } from './game-box/GameBox.svelte';
|
10
|
+
export { default as GridLayers } from './grid-layers/GridLayers.svelte';
|
11
|
+
export { default as VirtualViewport } from './virtual-viewport/VirtualViewport.svelte';
|
@@ -1,3 +1,57 @@
|
|
1
|
+
/**
|
2
|
+
* Manages responsive design scaling by calculating and applying scale factors
|
3
|
+
* based on container dimensions and design system requirements.
|
4
|
+
*
|
5
|
+
* @param {Object} options - Configuration options
|
6
|
+
* @param {HTMLElement} options.container - The container element to apply scaling to
|
7
|
+
* @param {Object} options.design - The base design dimensions
|
8
|
+
* @param {number} options.design.width - The reference design width
|
9
|
+
* @param {number} options.design.height - The reference design height
|
10
|
+
* @param {Object} options.clamping - The min/max values for various scale factors
|
11
|
+
* @param {Object} options.clamping.ui - UI element scaling constraints
|
12
|
+
* @param {number} options.clamping.ui.min - Minimum UI scale factor
|
13
|
+
* @param {number} options.clamping.ui.max - Maximum UI scale factor
|
14
|
+
* @param {Object} options.clamping.textBase - Base text scaling constraints
|
15
|
+
* @param {number} options.clamping.textBase.min - Minimum base text scale factor
|
16
|
+
* @param {number} options.clamping.textBase.max - Maximum base text scale factor
|
17
|
+
* @param {Object} options.clamping.textHeading - Heading text scaling constraints
|
18
|
+
* @param {number} options.clamping.textHeading.min - Minimum heading text scale factor
|
19
|
+
* @param {number} options.clamping.textHeading.max - Maximum heading text scale factor
|
20
|
+
* @param {Object} options.clamping.textUi - UI text scaling constraints
|
21
|
+
* @param {number} options.clamping.textUi.min - Minimum UI text scale factor
|
22
|
+
* @param {number} options.clamping.textUi.max - Maximum UI text scale factor
|
23
|
+
* @param {Function} [options.getDimensions] - Optional function to get width and height
|
24
|
+
* @param {boolean} [options.useResizeObserver=true] - Whether to use ResizeObserver
|
25
|
+
*
|
26
|
+
* @returns {()=>void} A cleanup function that removes event listeners and observers
|
27
|
+
*/
|
28
|
+
export function enableContainerScaling({ container, design, clamping, getDimensions, useResizeObserver }: {
|
29
|
+
container: HTMLElement;
|
30
|
+
design: {
|
31
|
+
width: number;
|
32
|
+
height: number;
|
33
|
+
};
|
34
|
+
clamping: {
|
35
|
+
ui: {
|
36
|
+
min: number;
|
37
|
+
max: number;
|
38
|
+
};
|
39
|
+
textBase: {
|
40
|
+
min: number;
|
41
|
+
max: number;
|
42
|
+
};
|
43
|
+
textHeading: {
|
44
|
+
min: number;
|
45
|
+
max: number;
|
46
|
+
};
|
47
|
+
textUi: {
|
48
|
+
min: number;
|
49
|
+
max: number;
|
50
|
+
};
|
51
|
+
};
|
52
|
+
getDimensions?: Function;
|
53
|
+
useResizeObserver?: boolean;
|
54
|
+
}): () => void;
|
1
55
|
/**
|
2
56
|
* Manages responsive design scaling by calculating and applying scale factors
|
3
57
|
* based on viewport dimensions and design system requirements.
|
@@ -1,5 +1,136 @@
|
|
1
1
|
import { clamp } from '../css/clamp.js';
|
2
2
|
|
3
|
+
/**
|
4
|
+
* Manages responsive design scaling by calculating and applying scale factors
|
5
|
+
* based on container dimensions and design system requirements.
|
6
|
+
*
|
7
|
+
* @param {Object} options - Configuration options
|
8
|
+
* @param {HTMLElement} options.container - The container element to apply scaling to
|
9
|
+
* @param {Object} options.design - The base design dimensions
|
10
|
+
* @param {number} options.design.width - The reference design width
|
11
|
+
* @param {number} options.design.height - The reference design height
|
12
|
+
* @param {Object} options.clamping - The min/max values for various scale factors
|
13
|
+
* @param {Object} options.clamping.ui - UI element scaling constraints
|
14
|
+
* @param {number} options.clamping.ui.min - Minimum UI scale factor
|
15
|
+
* @param {number} options.clamping.ui.max - Maximum UI scale factor
|
16
|
+
* @param {Object} options.clamping.textBase - Base text scaling constraints
|
17
|
+
* @param {number} options.clamping.textBase.min - Minimum base text scale factor
|
18
|
+
* @param {number} options.clamping.textBase.max - Maximum base text scale factor
|
19
|
+
* @param {Object} options.clamping.textHeading - Heading text scaling constraints
|
20
|
+
* @param {number} options.clamping.textHeading.min - Minimum heading text scale factor
|
21
|
+
* @param {number} options.clamping.textHeading.max - Maximum heading text scale factor
|
22
|
+
* @param {Object} options.clamping.textUi - UI text scaling constraints
|
23
|
+
* @param {number} options.clamping.textUi.min - Minimum UI text scale factor
|
24
|
+
* @param {number} options.clamping.textUi.max - Maximum UI text scale factor
|
25
|
+
* @param {Function} [options.getDimensions] - Optional function to get width and height
|
26
|
+
* @param {boolean} [options.useResizeObserver=true] - Whether to use ResizeObserver
|
27
|
+
*
|
28
|
+
* @returns {()=>void} A cleanup function that removes event listeners and observers
|
29
|
+
*/
|
30
|
+
export function enableContainerScaling({
|
31
|
+
container,
|
32
|
+
design,
|
33
|
+
clamping,
|
34
|
+
getDimensions,
|
35
|
+
useResizeObserver = true
|
36
|
+
}) {
|
37
|
+
if (!container) {
|
38
|
+
throw new Error('Container element is required for enableContainerScaling');
|
39
|
+
}
|
40
|
+
|
41
|
+
let resizeObserver;
|
42
|
+
|
43
|
+
/**
|
44
|
+
* Updates CSS scale variables based on container dimensions
|
45
|
+
* and design system constraints
|
46
|
+
*/
|
47
|
+
function updateScaleValues() {
|
48
|
+
try {
|
49
|
+
let containerWidth, containerHeight;
|
50
|
+
|
51
|
+
// Use custom dimension getter if provided
|
52
|
+
if (typeof getDimensions === 'function') {
|
53
|
+
const dimensions = getDimensions();
|
54
|
+
containerWidth = dimensions.width;
|
55
|
+
containerHeight = dimensions.height;
|
56
|
+
} else {
|
57
|
+
// Otherwise use container's client dimensions
|
58
|
+
const rect = container.getBoundingClientRect();
|
59
|
+
containerWidth = rect.width;
|
60
|
+
containerHeight = rect.height;
|
61
|
+
}
|
62
|
+
|
63
|
+
// Skip update if dimensions are zero (container not visible)
|
64
|
+
if (containerWidth <= 0 || containerHeight <= 0) {
|
65
|
+
return;
|
66
|
+
}
|
67
|
+
|
68
|
+
// Calculate scale factors based on container size relative to design dimensions
|
69
|
+
const scaleW = containerWidth / design.width;
|
70
|
+
const scaleH = containerHeight / design.height;
|
71
|
+
|
72
|
+
// Use the smaller scale factor to ensure content fits within container
|
73
|
+
const scaleViewport = Math.min(scaleW, scaleH);
|
74
|
+
|
75
|
+
// Apply clamping to different element types
|
76
|
+
const scaleUI = clamp(clamping.ui.min, scaleViewport, clamping.ui.max);
|
77
|
+
|
78
|
+
const scaleTextBase = clamp(
|
79
|
+
clamping.textBase.min,
|
80
|
+
scaleViewport,
|
81
|
+
clamping.textBase.max
|
82
|
+
);
|
83
|
+
|
84
|
+
const scaleTextHeading = clamp(
|
85
|
+
clamping.textHeading.min,
|
86
|
+
scaleViewport,
|
87
|
+
clamping.textHeading.max
|
88
|
+
);
|
89
|
+
|
90
|
+
const scaleTextUi = clamp(
|
91
|
+
clamping.textUi.min,
|
92
|
+
scaleViewport,
|
93
|
+
clamping.textUi.max
|
94
|
+
);
|
95
|
+
|
96
|
+
// Set CSS custom properties on the container
|
97
|
+
container.style.setProperty('--scale-w', String(scaleW));
|
98
|
+
container.style.setProperty('--scale-h', String(scaleH));
|
99
|
+
container.style.setProperty('--scale-viewport', String(scaleViewport));
|
100
|
+
container.style.setProperty('--scale-ui', String(scaleUI));
|
101
|
+
container.style.setProperty('--scale-text-base', String(scaleTextBase));
|
102
|
+
container.style.setProperty(
|
103
|
+
'--scale-text-heading',
|
104
|
+
String(scaleTextHeading)
|
105
|
+
);
|
106
|
+
container.style.setProperty('--scale-text-ui', String(scaleTextUi));
|
107
|
+
} catch (error) {
|
108
|
+
console.error('Error updating container scale values:', error);
|
109
|
+
}
|
110
|
+
}
|
111
|
+
|
112
|
+
// Initialize scales
|
113
|
+
updateScaleValues();
|
114
|
+
|
115
|
+
// Set up ResizeObserver for container resize detection
|
116
|
+
if (useResizeObserver && typeof ResizeObserver !== 'undefined') {
|
117
|
+
resizeObserver = new ResizeObserver(updateScaleValues);
|
118
|
+
resizeObserver.observe(container);
|
119
|
+
} else {
|
120
|
+
// Fallback to window resize event
|
121
|
+
window.addEventListener('resize', updateScaleValues);
|
122
|
+
}
|
123
|
+
|
124
|
+
// Return cleanup function
|
125
|
+
return function cleanup() {
|
126
|
+
if (resizeObserver) {
|
127
|
+
resizeObserver.disconnect();
|
128
|
+
} else {
|
129
|
+
window.removeEventListener('resize', updateScaleValues);
|
130
|
+
}
|
131
|
+
};
|
132
|
+
}
|
133
|
+
|
3
134
|
/**
|
4
135
|
* Manages responsive design scaling by calculating and applying scale factors
|
5
136
|
* based on viewport dimensions and design system requirements.
|
package/package.json
CHANGED
@@ -1,112 +0,0 @@
|
|
1
|
-
<script>
|
2
|
-
import {
|
3
|
-
getGameWidthOnLandscape,
|
4
|
-
getGameWidthOnPortrait
|
5
|
-
} from './gamebox.util.js';
|
6
|
-
|
7
|
-
/**
|
8
|
-
* @type {{
|
9
|
-
* base?: string,
|
10
|
-
* bg?: string,
|
11
|
-
* classes?: string,
|
12
|
-
* style?: string,
|
13
|
-
* aspectOnLandscape? :number,
|
14
|
-
* aspectOnPortrait? :number,
|
15
|
-
* onLandscape?: import('svelte').Snippet,
|
16
|
-
* onPortrait?: import('svelte').Snippet
|
17
|
-
* } & { [attr: string]: any }}
|
18
|
-
*/
|
19
|
-
const {
|
20
|
-
// > Style
|
21
|
-
base,
|
22
|
-
bg,
|
23
|
-
classes,
|
24
|
-
style,
|
25
|
-
|
26
|
-
// > Functional
|
27
|
-
aspectOnLandscape,
|
28
|
-
aspectOnPortrait,
|
29
|
-
|
30
|
-
// >Snippets
|
31
|
-
snippetLandscape,
|
32
|
-
snippetPortrait
|
33
|
-
} = $props();
|
34
|
-
|
35
|
-
// > Game width and height
|
36
|
-
|
37
|
-
let windowWidth = $state();
|
38
|
-
let windowHeight = $state();
|
39
|
-
|
40
|
-
let gameWidth = $state();
|
41
|
-
let gameHeight = $state();
|
42
|
-
|
43
|
-
let isLandscape = $derived(gameWidth > gameHeight);
|
44
|
-
|
45
|
-
$effect(() => {
|
46
|
-
// Determine game width and height from
|
47
|
-
// window dimensions and desired game aspect
|
48
|
-
|
49
|
-
let gameAspect;
|
50
|
-
|
51
|
-
if (windowWidth > windowHeight) {
|
52
|
-
gameWidth = getGameWidthOnLandscape({
|
53
|
-
windowWidth,
|
54
|
-
windowHeight,
|
55
|
-
aspectOnLandscape
|
56
|
-
});
|
57
|
-
|
58
|
-
gameAspect = aspectOnLandscape;
|
59
|
-
} else {
|
60
|
-
gameWidth = getGameWidthOnPortrait({
|
61
|
-
windowWidth,
|
62
|
-
windowHeight,
|
63
|
-
aspectOnPortrait
|
64
|
-
});
|
65
|
-
|
66
|
-
gameAspect = aspectOnPortrait;
|
67
|
-
}
|
68
|
-
|
69
|
-
if (gameAspect) {
|
70
|
-
gameHeight = gameWidth / gameAspect;
|
71
|
-
} else {
|
72
|
-
gameHeight = windowHeight;
|
73
|
-
}
|
74
|
-
});
|
75
|
-
|
76
|
-
// $inspect({ windowWidth, windowHeight, gameWidth, gameHeight, isLandscape });
|
77
|
-
|
78
|
-
// $effect(() => {
|
79
|
-
// console.log({
|
80
|
-
// windowWidth,
|
81
|
-
// windowHeight,
|
82
|
-
// gameWidth,
|
83
|
-
// gameHeight,
|
84
|
-
// isLandscape
|
85
|
-
// });
|
86
|
-
// });
|
87
|
-
</script>
|
88
|
-
|
89
|
-
<svelte:window bind:innerWidth={windowWidth} bind:innerHeight={windowHeight} />
|
90
|
-
|
91
|
-
{#if gameHeight}
|
92
|
-
<!-- <div
|
93
|
-
data-boxes="game-box"
|
94
|
-
class="{base} {bg} {classes}"
|
95
|
-
style="width: {gameWidth}px; height: {gameHeight}px;--game-width={gameWidth};--game-height={gameHeight}; {style}" -->
|
96
|
-
|
97
|
-
<div
|
98
|
-
data-boxes="game-box"
|
99
|
-
class="{base} {bg} {classes}"
|
100
|
-
style:width="{gameWidth}px"
|
101
|
-
style:height="{gameHeight}px"
|
102
|
-
style:--game-width={gameWidth}
|
103
|
-
style:--game-height={gameHeight}
|
104
|
-
{style}
|
105
|
-
>
|
106
|
-
{#if isLandscape}
|
107
|
-
{@render snippetLandscape()}
|
108
|
-
{:else}
|
109
|
-
{@render snippetPortrait()}
|
110
|
-
{/if}
|
111
|
-
</div>
|
112
|
-
{/if}
|
@@ -1,28 +0,0 @@
|
|
1
|
-
export default GameBox;
|
2
|
-
type GameBox = {
|
3
|
-
$on?(type: string, callback: (e: any) => void): () => void;
|
4
|
-
$set?(props: Partial<{
|
5
|
-
base?: string;
|
6
|
-
bg?: string;
|
7
|
-
classes?: string;
|
8
|
-
style?: string;
|
9
|
-
aspectOnLandscape?: number;
|
10
|
-
aspectOnPortrait?: number;
|
11
|
-
onLandscape?: Snippet<[]>;
|
12
|
-
onPortrait?: Snippet<[]>;
|
13
|
-
} & {
|
14
|
-
[attr: string]: any;
|
15
|
-
}>): void;
|
16
|
-
};
|
17
|
-
declare const GameBox: import("svelte").Component<{
|
18
|
-
base?: string;
|
19
|
-
bg?: string;
|
20
|
-
classes?: string;
|
21
|
-
style?: string;
|
22
|
-
aspectOnLandscape?: number;
|
23
|
-
aspectOnPortrait?: number;
|
24
|
-
onLandscape?: import("svelte").Snippet;
|
25
|
-
onPortrait?: import("svelte").Snippet;
|
26
|
-
} & {
|
27
|
-
[attr: string]: any;
|
28
|
-
}, {}, "">;
|
@@ -1,82 +0,0 @@
|
|
1
|
-
<script>
|
2
|
-
/**
|
3
|
-
* Grid Layers component
|
4
|
-
* This is a grid with only one cell. All direct children are
|
5
|
-
* place in the same cell and form a visually stacked component.
|
6
|
-
*
|
7
|
-
* This can be used to place e.g. texts over an image. Place the
|
8
|
-
* image in a layer and the text in another. The standard grid
|
9
|
-
* content placement options can be used.
|
10
|
-
*
|
11
|
-
* Following component guidelines from Skeleton
|
12
|
-
* @see https://next.skeleton.dev/docs/resources/contribute/components
|
13
|
-
*/
|
14
|
-
|
15
|
-
/**
|
16
|
-
* @type {{
|
17
|
-
* base?: string,
|
18
|
-
* bg?: string,
|
19
|
-
* padding?: string,
|
20
|
-
* margin?: string,
|
21
|
-
* height?: string,
|
22
|
-
* classes?: string,
|
23
|
-
* style?: string,
|
24
|
-
* boxBase?: string,
|
25
|
-
* boxBg?: string,
|
26
|
-
* boxPadding?: string,
|
27
|
-
* boxMargin?: string,
|
28
|
-
* boxClasses?: string,
|
29
|
-
* boxAttrs?: { [attr: string]: * },
|
30
|
-
* children: import('svelte').Snippet
|
31
|
-
* } & { [attr: string]: any }}
|
32
|
-
*/
|
33
|
-
const {
|
34
|
-
// Style
|
35
|
-
base,
|
36
|
-
bg,
|
37
|
-
padding,
|
38
|
-
margin,
|
39
|
-
height = 'h-full',
|
40
|
-
classes,
|
41
|
-
style,
|
42
|
-
boxBase,
|
43
|
-
boxBg,
|
44
|
-
boxPadding,
|
45
|
-
boxMargin,
|
46
|
-
boxClasses,
|
47
|
-
|
48
|
-
// Snippets
|
49
|
-
children,
|
50
|
-
|
51
|
-
// Attributes
|
52
|
-
...attrs
|
53
|
-
} = $props();
|
54
|
-
</script>
|
55
|
-
|
56
|
-
<div
|
57
|
-
data-hk-grid-layers-box
|
58
|
-
class="{boxBase} {boxBg} {boxPadding} {boxMargin} {boxClasses}"
|
59
|
-
{...attrs}
|
60
|
-
>
|
61
|
-
<div
|
62
|
-
data-hk-grid-layers
|
63
|
-
class="grid grid-cols-1 grid-rows-1 {base} {bg} {height} {classes} {margin} {padding}"
|
64
|
-
{style}
|
65
|
-
>
|
66
|
-
{@render children()}
|
67
|
-
</div>
|
68
|
-
</div>
|
69
|
-
|
70
|
-
<style>
|
71
|
-
[data-hk-grid-layers] > :global(.area-above) {
|
72
|
-
grid-area: 1/1/2/2;
|
73
|
-
}
|
74
|
-
|
75
|
-
[data-hk-grid-layers] > :global(*) {
|
76
|
-
grid-area: 2/1/3/2;
|
77
|
-
}
|
78
|
-
|
79
|
-
[data-hk-grid-layers] > :global(.area-below) {
|
80
|
-
grid-area: 3/1/4/2;
|
81
|
-
}
|
82
|
-
</style>
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|