@smartnet360/svelte-components 0.0.1-beta.3 → 0.0.2

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,34 @@
1
+ export type Scale = "percent" | "absolute";
2
+ export type Aggregation = "avg" | "max" | "min" | "sum";
3
+ export interface KPI {
4
+ rawName: string;
5
+ name: string;
6
+ scale: Scale;
7
+ unit: string;
8
+ color?: string;
9
+ aggregation: Aggregation;
10
+ }
11
+ export interface Chart {
12
+ pos: 1 | 2 | 3 | 4;
13
+ title: string;
14
+ yLeft: KPI[];
15
+ yRight: KPI[];
16
+ }
17
+ export interface Section {
18
+ id: string;
19
+ title: string;
20
+ charts: [Chart, Chart, Chart, Chart];
21
+ }
22
+ export type Mode = "tabs" | "scrollspy";
23
+ export interface Layout {
24
+ layoutName: string;
25
+ sections: Section[];
26
+ }
27
+ export interface ChartMarker {
28
+ date: string | Date;
29
+ label: string;
30
+ color?: string;
31
+ style?: 'solid' | 'dashed' | 'dotted';
32
+ showLabel?: boolean;
33
+ category?: 'release' | 'incident' | 'maintenance' | 'other';
34
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,13 @@
1
+ import type { KPI } from './charts.model.js';
2
+ export type AggregationType = 'avg' | 'sum' | 'max' | 'min';
3
+ export declare function aggregateValue(values: number[], aggregation: AggregationType): number;
4
+ export declare function processKPIData(data: any[], kpi: KPI): {
5
+ values: number[];
6
+ aggregated: number;
7
+ };
8
+ export declare function createTimeSeriesTrace(data: any[], kpi: KPI, timestampField?: string, yaxis?: 'y1' | 'y2'): any;
9
+ export declare function createBarTrace(data: any[], kpi: KPI, timestampField?: string, yaxis?: 'y1' | 'y2'): any;
10
+ export declare function createPieTrace(data: any[], kpi: KPI, timestampField?: string): any;
11
+ export declare function getYAxisTitle(kpis: KPI[]): string;
12
+ export declare function formatValue(value: number, scale: 'percent' | 'absolute', unit: string): string;
13
+ export declare function createDefaultPlotlyLayout(title?: string): any;
@@ -0,0 +1,131 @@
1
+ export function aggregateValue(values, aggregation) {
2
+ switch (aggregation) {
3
+ case 'avg':
4
+ return values.reduce((sum, val) => sum + val, 0) / values.length;
5
+ case 'sum':
6
+ return values.reduce((sum, val) => sum + val, 0);
7
+ case 'max':
8
+ return Math.max(...values);
9
+ case 'min':
10
+ return Math.min(...values);
11
+ default:
12
+ return values[0] || 0;
13
+ }
14
+ }
15
+ export function processKPIData(data, kpi) {
16
+ const rawValues = data
17
+ .map(row => {
18
+ const val = row[kpi.rawName];
19
+ return typeof val === 'number' ? val : parseFloat(val);
20
+ })
21
+ .filter(val => !isNaN(val));
22
+ const aggregated = aggregateValue(rawValues, kpi.aggregation);
23
+ return {
24
+ values: rawValues,
25
+ aggregated
26
+ };
27
+ }
28
+ export function createTimeSeriesTrace(data, kpi, timestampField = 'TIMESTAMP', yaxis = 'y1') {
29
+ const processed = processKPIData(data, kpi);
30
+ const timestamps = data.map(row => row[timestampField]);
31
+ return {
32
+ x: timestamps,
33
+ y: processed.values,
34
+ type: 'scatter',
35
+ mode: 'lines+markers',
36
+ name: kpi.name,
37
+ yaxis: yaxis,
38
+ line: {
39
+ color: kpi.color || '#1f77b4',
40
+ width: 2
41
+ },
42
+ marker: {
43
+ size: 4
44
+ }
45
+ };
46
+ }
47
+ export function createBarTrace(data, kpi, timestampField = 'TIMESTAMP', yaxis = 'y1') {
48
+ const processed = processKPIData(data, kpi);
49
+ const timestamps = data.map(row => row[timestampField]);
50
+ return {
51
+ x: timestamps,
52
+ y: processed.values,
53
+ type: 'bar',
54
+ name: kpi.name,
55
+ yaxis: yaxis,
56
+ marker: {
57
+ color: kpi.color || '#1f77b4'
58
+ }
59
+ };
60
+ }
61
+ export function createPieTrace(data, kpi, timestampField = 'TIMESTAMP') {
62
+ const processed = processKPIData(data, kpi);
63
+ const timestamps = data.map(row => row[timestampField]);
64
+ // For pie charts, we'll show the latest value
65
+ const latestValue = processed.values[processed.values.length - 1];
66
+ const latestTimestamp = timestamps[timestamps.length - 1];
67
+ return {
68
+ values: [latestValue],
69
+ labels: [kpi.name],
70
+ type: 'pie',
71
+ name: `${kpi.name} (${latestTimestamp})`,
72
+ marker: {
73
+ colors: [kpi.color || '#1f77b4']
74
+ }
75
+ };
76
+ }
77
+ export function getYAxisTitle(kpis) {
78
+ if (kpis.length === 0)
79
+ return '';
80
+ // If all KPIs have the same unit, use that
81
+ const units = [...new Set(kpis.map(kpi => kpi.unit))];
82
+ return units.length === 1 ? units[0] : 'Mixed Units';
83
+ }
84
+ export function formatValue(value, scale, unit) {
85
+ if (scale === 'percent') {
86
+ return `${value.toFixed(2)}${unit}`;
87
+ }
88
+ return `${value.toLocaleString()}${unit}`;
89
+ }
90
+ export function createDefaultPlotlyLayout(title) {
91
+ return {
92
+ title: title ? {
93
+ text: title,
94
+ font: {
95
+ size: 16,
96
+ color: '#2c3e50',
97
+ weight: 600
98
+ },
99
+ x: 0.5,
100
+ xanchor: 'center'
101
+ } : undefined,
102
+ showlegend: true,
103
+ legend: {
104
+ x: 1,
105
+ y: 1,
106
+ xanchor: 'right',
107
+ yanchor: 'top',
108
+ font: { size: 12 }
109
+ },
110
+ xaxis: {
111
+ title: {
112
+ text: 'Time',
113
+ font: { size: 12, color: '#7f8c8d' }
114
+ },
115
+ showgrid: true,
116
+ gridcolor: '#ecf0f1',
117
+ linecolor: '#bdc3c7',
118
+ tickfont: { size: 11 }
119
+ },
120
+ yaxis: {
121
+ showgrid: true,
122
+ gridcolor: '#ecf0f1',
123
+ linecolor: '#bdc3c7',
124
+ tickfont: { size: 11 }
125
+ },
126
+ margin: { l: 60, r: 60, t: 60, b: 50 },
127
+ paper_bgcolor: 'rgba(0,0,0,0)',
128
+ plot_bgcolor: 'rgba(0,0,0,0)',
129
+ font: { family: 'Inter, -apple-system, BlinkMacSystemFont, sans-serif' }
130
+ };
131
+ }
@@ -0,0 +1,7 @@
1
+ export { default as ChartComponent } from './ChartComponent.svelte';
2
+ export { default as ChartCard } from './ChartCard.svelte';
3
+ export type { Layout, Section, Chart, KPI, Mode, Scale, Aggregation, ChartMarker } from './charts.model.js';
4
+ export { createTimeSeriesTrace, createBarTrace, createPieTrace, getYAxisTitle, formatValue, aggregateValue, processKPIData, createDefaultPlotlyLayout } from './data-utils.js';
5
+ export type { AggregationType } from './data-utils.js';
6
+ export { adaptPlotlyLayout, getSizeCategory, createMarkerShapes, createMarkerAnnotations, addMarkersToLayout } from './adapt.js';
7
+ export type { ContainerSize, ChartInfo, AdaptationConfig } from './adapt.js';
@@ -0,0 +1,4 @@
1
+ export { default as ChartComponent } from './ChartComponent.svelte';
2
+ export { default as ChartCard } from './ChartCard.svelte';
3
+ export { createTimeSeriesTrace, createBarTrace, createPieTrace, getYAxisTitle, formatValue, aggregateValue, processKPIData, createDefaultPlotlyLayout } from './data-utils.js';
4
+ export { adaptPlotlyLayout, getSizeCategory, createMarkerShapes, createMarkerAnnotations, addMarkersToLayout } from './adapt.js';
@@ -0,0 +1,4 @@
1
+ declare module 'plotly.js-dist-min' {
2
+ const Plotly: any;
3
+ export default Plotly;
4
+ }
@@ -18,6 +18,7 @@
18
18
  export let theme: 'light' | 'dark' = 'light';
19
19
  export let maxGrids: number = 10;
20
20
  export let onLaunch: ((grid: GridConfiguration) => void) | null = null;
21
+ export let onOpen: ((grids: GridConfiguration[]) => void) | null = null;
21
22
 
22
23
  // State
23
24
  let savedGrids: GridConfiguration[] = [];
@@ -164,6 +165,7 @@
164
165
  // Load data on mount
165
166
  onMount(() => {
166
167
  loadSavedGrids();
168
+ if (onOpen) onOpen(savedGrids);
167
169
 
168
170
  // Add keyboard event listener
169
171
  const handleKeydown = (event: KeyboardEvent) => {
@@ -19,6 +19,7 @@ declare const Desktop: $$__sveltets_2_IsomorphicComponent<{
19
19
  theme?: "light" | "dark";
20
20
  maxGrids?: number;
21
21
  onLaunch?: ((grid: GridConfiguration) => void) | null;
22
+ onOpen?: ((grids: GridConfiguration[]) => void) | null;
22
23
  }, {
23
24
  [evt: string]: CustomEvent<any>;
24
25
  }, {}, {}, string>;
@@ -77,7 +77,7 @@
77
77
  </script>
78
78
 
79
79
  <!-- Slot rendering snippet -->
80
- {#snippet slotContent(slotId, slotName)}
80
+ {#snippet slotContent(slotId: string, slotName: string)}
81
81
  {@const slot = renderSlot(slotId, slotName)}
82
82
  {#if slot.hasComponent}
83
83
  <div class="component-wrapper">
package/dist/index.d.ts CHANGED
@@ -1 +1,2 @@
1
1
  export { Half, Quarter, ResizeHandle, resizeStore, Desktop, GridSelector, GridRenderer, GridViewer, type ComponentConfig, getAllLayouts, getLayoutById, getLayoutsByCategory, getLayoutsOrdered, validateComponentAssignments, createGridConfiguration, type GridLayoutDefinition, type GridSlot, type ComponentAssignment, type GridConfiguration, createWindowLauncher, createTabLauncher, createNavigationLauncher, createModalLauncher } from './Desktop/index.js';
2
+ export { ChartComponent, ChartCard, type Layout, type Section, type Chart, type KPI, type Mode, type Scale, type Aggregation, createTimeSeriesTrace, createBarTrace, createPieTrace, getYAxisTitle, formatValue, aggregateValue, processKPIData, createDefaultPlotlyLayout, type AggregationType } from './Charts/index.js';
package/dist/index.js CHANGED
@@ -1 +1,2 @@
1
1
  export { Half, Quarter, ResizeHandle, resizeStore, Desktop, GridSelector, GridRenderer, GridViewer, getAllLayouts, getLayoutById, getLayoutsByCategory, getLayoutsOrdered, validateComponentAssignments, createGridConfiguration, createWindowLauncher, createTabLauncher, createNavigationLauncher, createModalLauncher } from './Desktop/index.js';
2
+ export { ChartComponent, ChartCard, createTimeSeriesTrace, createBarTrace, createPieTrace, getYAxisTitle, formatValue, aggregateValue, processKPIData, createDefaultPlotlyLayout } from './Charts/index.js';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@smartnet360/svelte-components",
3
- "version": "0.0.1-beta.3",
3
+ "version": "0.0.2",
4
4
  "scripts": {
5
5
  "dev": "vite dev",
6
6
  "build": "vite build && npm run prepack",
@@ -11,14 +11,13 @@
11
11
  "check:watch": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json --watch",
12
12
  "format": "prettier --write .",
13
13
  "lint": "prettier --check . && eslint .",
14
- "release:beta": "npm version prerelease --preid=beta && npm publish --tag beta --access public",
15
- "release:alpha": "npm version prerelease --preid=alpha && npm publish --tag alpha --access public",
16
- "release:patch": "npm version patch && npm publish --tag latest --access public",
17
- "release:minor": "npm version minor && npm publish --tag latest --access public",
18
- "release:major": "npm version major && npm publish --tag latest --access public"
14
+ "release:patch": "npm version patch && npm publish --access public",
15
+ "release:minor": "npm version minor && npm publish --access public",
16
+ "release:major": "npm version major && npm publish --access public"
19
17
  },
20
18
  "files": [
21
- "dist"
19
+ "dist",
20
+ "!dist/**/*.md"
22
21
  ],
23
22
  "sideEffects": [
24
23
  "**/*.css"
@@ -60,6 +59,7 @@
60
59
  "svelte"
61
60
  ],
62
61
  "dependencies": {
63
- "bootstrap": "^5.2.3"
62
+ "bootstrap": "^5.2.3",
63
+ "plotly.js-dist-min": "^3.1.0"
64
64
  }
65
65
  }
@@ -1,331 +0,0 @@
1
- # Desktop Grid Component
2
-
3
- ## Overview
4
-
5
- The Desktop Grid component provides a flexible, component-based approach to creating complex desktop layouts with dynamic resizing capabilities. The system uses composable Half and Quarter components that can be nested to build any desired layout, combined with a ResizeHandle for interactive resizing.
6
-
7
- ## Component-Based Approach
8
-
9
- ### Core Components
10
-
11
- - **Half**: Flexible component for splitting space in half (left, right, top, bottom)
12
- - **Quarter**: Component that renders two quarters inside one half with dynamic internal proportions
13
- - **ResizeHandle**: Interactive draggable handle for resizing grid areas
14
- - **resizeStore**: Svelte store for managing resize state across components
15
-
16
- ### Advantages
17
-
18
- - **Explicit**: Code clearly shows the intended layout
19
- - **Interactive**: Built-in resize handles for dynamic layout changes
20
- - **Reusable**: Components can be combined in various ways
21
- - **Maintainable**: Each component handles one specific responsibility
22
- - **Flexible**: Easy to nest and compose complex layouts
23
- - **Stateful**: Shared store manages resize state across components
24
-
25
- ## Usage
26
-
27
- ### Half Component
28
-
29
- ```svelte
30
- <script lang="ts">
31
- export let position: 'left' | 'right' | 'top' | 'bottom' = 'left';
32
- </script>
33
-
34
- <div class="half {position}">
35
- <slot />
36
- </div>
37
-
38
- <style>
39
- .half {
40
- display: grid;
41
- place-items: center;
42
- border: 1px solid #ccc;
43
- }
44
-
45
- /* Positions */
46
- .left { grid-column: 1 / 2; grid-row: 1 / -1; }
47
- .right { grid-column: 2 / 3; grid-row: 1 / -1; }
48
- .top { grid-row: 1 / 2; grid-column: 1 / -1; }
49
- .bottom{ grid-row: 2 / 3; grid-column: 1 / -1; }
50
- </style>
51
- ```
52
-
53
- ### Quarter Component
54
-
55
- ```svelte
56
- <script lang="ts">
57
- export let position: 'left' | 'right' | 'top' | 'bottom';
58
- export let topHeight: number = 50; // Percentage for top/left section
59
- export let bottomHeight: number = 50; // Percentage for bottom/right section
60
- </script>
61
-
62
- <div class="quarters {position}" style="--top-height: {topHeight}%; --bottom-height: {bottomHeight}%">
63
- <div class="quarter top-or-left">
64
- <slot name="top-or-left" />
65
- </div>
66
- <div class="quarter bottom-or-right">
67
- <slot name="bottom-or-right" />
68
- </div>
69
- </div>
70
-
71
- <style>
72
- .quarters {
73
- border: 1px solid #aaa;
74
- display: grid;
75
- overflow: hidden;
76
- width: 100%;
77
- height: 100%;
78
- }
79
-
80
- /* Left and Right quarters are stacked (vertical split) */
81
- .quarters.left,
82
- .quarters.right {
83
- grid-template-rows: var(--top-height) var(--bottom-height);
84
- grid-template-columns: 1fr;
85
- }
86
-
87
- /* Top and Bottom quarters are side-by-side (horizontal split) */
88
- .quarters.top,
89
- .quarters.bottom {
90
- grid-template-columns: var(--top-height) var(--bottom-height);
91
- grid-template-rows: 1fr;
92
- }
93
-
94
- ### ResizeHandle Component
95
-
96
- ```svelte
97
- <script lang="ts">
98
- import { createEventDispatcher } from 'svelte';
99
-
100
- export let position: 'center' | 'left' | 'right' | 'top' | 'bottom' = 'center';
101
- export let horizontalSize: number = 50;
102
- export let verticalSize: number = 50;
103
-
104
- const dispatch = createEventDispatcher();
105
- </script>
106
-
107
- <div
108
- class="resize-handle {position}"
109
- class:dragging={isDragging}
110
- style="cursor: {cursorStyle}"
111
- on:mousedown={handleMouseDown}
112
- role="button"
113
- tabindex="0"
114
- aria-label="Resize handle"
115
- >
116
- <div class="handle-indicator"></div>
117
- </div>
118
-
119
- <!-- Dispatches 'resize' event with { horizontalSize, verticalSize } -->
120
- ```
121
-
122
- ### resizeStore
123
-
124
- ```typescript
125
- import { writable } from 'svelte/store';
126
-
127
- export interface ResizeState {
128
- leftWidth: number;
129
- rightWidth: number;
130
- topHeight: number;
131
- bottomHeight: number;
132
- quarterSplit: number;
133
- }
134
-
135
- const resizeStore = createResizeStore();
136
-
137
- export const resizeStore = {
138
- subscribe: resizeStore.subscribe,
139
- set: resizeStore.set,
140
- update,
141
- reset: () => set(initialState),
142
- updateLeftWidth: (width: number) => update(state => ({...})),
143
- updateTopHeight: (height: number) => update(state => ({...})),
144
- update2D: (horizontalSize: number, verticalSize: number) => update(state => ({
145
- ...state,
146
- leftWidth: Math.max(10, Math.min(90, horizontalSize)),
147
- rightWidth: 100 - Math.max(10, Math.min(90, horizontalSize)),
148
- topHeight: Math.max(10, Math.min(90, verticalSize)),
149
- bottomHeight: 100 - Math.max(10, Math.min(90, verticalSize))
150
- }))
151
- };
152
- ```
153
-
154
- ## Usage Examples
155
-
156
- ### Basic Resizable Layout with Store
157
-
158
- ```svelte
159
- <script lang="ts">
160
- import { Quarter, ResizeHandle, resizeStore } from './lib/index.js';
161
-
162
- let leftWidth = 50;
163
- let rightWidth = 50;
164
- let topHeight = 50;
165
- let bottomHeight = 50;
166
-
167
- // Subscribe to store changes
168
- resizeStore.subscribe((state) => {
169
- leftWidth = state.leftWidth;
170
- rightWidth = state.rightWidth;
171
- topHeight = state.topHeight;
172
- bottomHeight = state.bottomHeight;
173
- });
174
-
175
- function handleResize(event: CustomEvent) {
176
- const { horizontalSize, verticalSize } = event.detail;
177
- resizeStore.update2D(horizontalSize, verticalSize);
178
- }
179
- </script>
180
-
181
- <div class="desktop" style="grid-template-columns: {leftWidth}% {rightWidth}%; grid-template-rows: {topHeight}% {bottomHeight}%">
182
- <Quarter position="left" {topHeight} {bottomHeight}>
183
- <Chart slot="top-or-left" />
184
- <List slot="bottom-or-right" />
185
- </Quarter>
186
-
187
- <Quarter position="right" {topHeight} {bottomHeight}>
188
- <Form slot="top-or-left" />
189
- <Text slot="bottom-or-right" />
190
- </Quarter>
191
-
192
- <ResizeHandle
193
- position="center"
194
- horizontalSize={leftWidth}
195
- verticalSize={topHeight}
196
- on:resize={handleResize}
197
- />
198
- </div>
199
- ```
200
-
201
- ### Left Half + Right Quarters with Resizing
202
-
203
- ```svelte
204
- <div class="desktop" style="grid-template-columns: {leftWidth}% {rightWidth}%; grid-template-rows: {topHeight}% {bottomHeight}%">
205
- <Half position="left">
206
- <Chart />
207
- </Half>
208
-
209
- <Quarter position="right" {topHeight} {bottomHeight}>
210
- <Map slot="top-or-left" />
211
- <Table slot="bottom-or-right" />
212
- </Quarter>
213
-
214
- <ResizeHandle
215
- position="center"
216
- horizontalSize={leftWidth}
217
- verticalSize={topHeight}
218
- on:resize={handleResize}
219
- />
220
- </div>
221
- ```
222
-
223
- ## Visual Examples
224
-
225
- ### Dynamic Resizable Layout
226
- ```
227
- +---------+----+ +-----+--+ +---+-----+
228
- | | 25 | | |25| | | 75 |
229
- | 50% +----+ → | 60% +--+ → |50%|+----+
230
- | | 25 | | |25| | | 25 |
231
- +---------+----+ +-----+--+ +---+-----+
232
- ```
233
-
234
- ### Desktop Container Setup
235
- ```css
236
- .desktop {
237
- display: grid;
238
- /* Dynamic columns and rows controlled by store */
239
- grid-template-columns: var(--left-width, 50%) var(--right-width, 50%);
240
- grid-template-rows: var(--top-height, 50%) var(--bottom-height, 50%);
241
- height: 100vh;
242
- position: relative; /* For absolute positioned resize handle */
243
- }
244
- ```
245
-
246
- ### Resize Handle Positioning
247
- ```css
248
- .resize-handle.center {
249
- position: absolute;
250
- top: 50%;
251
- left: 50%;
252
- transform: translate(-50%, -50%);
253
- z-index: 1000;
254
- }
255
- ```
256
-
257
- ## Features
258
-
259
- ### ✅ Dynamic Resizing
260
- - **ResizeHandle**: Interactive draggable handle for 2D resizing
261
- - **Real-time Updates**: Components respond immediately to size changes
262
- - **Constrained Values**: Automatic min/max limits (10%-90%)
263
- - **Smooth Animation**: CSS transitions for visual feedback
264
-
265
- ### ✅ State Management
266
- - **Shared Store**: Centralized resize state across all components
267
- - **Reactive Updates**: Automatic UI updates when store changes
268
- - **TypeScript Support**: Full type safety for resize operations
269
-
270
- ### ✅ Flexible Layouts
271
- - **Dynamic Proportions**: Quarter components accept custom height ratios
272
- - **Nested Components**: Combine Half and Quarter components freely
273
- - **CSS Grid**: Modern layout system with full browser support
274
-
275
- ### ✅ Component Architecture
276
- - **Slot-based**: Flexible content insertion with named slots
277
- - **Composable**: Easy to combine and nest components
278
- - **Accessible**: Proper ARIA labels and keyboard navigation
279
-
280
- ## Current Implementation Status
281
-
282
- ### ✅ Completed Features
283
- - Half and Quarter layout components
284
- - Interactive ResizeHandle with mouse/touch support
285
- - Svelte store for state management
286
- - Dynamic Quarter component proportions
287
- - Test page with dummy components
288
- - Full TypeScript support
289
- - CSS Grid responsive layouts
290
-
291
- ### 🔄 Future Enhancements
292
- - Add keyboard navigation for resize handles
293
- - Implement maximize/fullscreen functionality
294
- - Add animation presets for smooth transitions
295
- - Create additional layout primitives (thirds, fifths)
296
- - Add drag-to-resize from component edges
297
-
298
- ## Test Implementation
299
-
300
- The system includes a comprehensive test page (`/src/routes/test/+page.svelte`) that demonstrates:
301
-
302
- ### Dummy Components
303
- - **Chart**: Interactive bar chart with customizable data
304
- - **List**: Task list with checkboxes for project management
305
- - **Form**: Working contact form with validation
306
- - **Text**: Scrollable content area for documentation
307
-
308
- ### Test Features
309
- - **Live Resizing**: Drag the center handle to resize all quadrants
310
- - **Debug Info**: Real-time display of current proportions
311
- - **Responsive Design**: Components adapt to size changes
312
- - **Interactive Content**: All dummy components are fully functional
313
-
314
- ### Usage in Test
315
- ```svelte
316
- <Quarter position="left" {topHeight} {bottomHeight}>
317
- <Chart slot="top-or-left" title="Sales Analytics" data={[25, 45, 30, 60, 40]} />
318
- <List slot="bottom-or-right" title="Project Tasks" items={["Design review", "Code review", "Testing", "Deployment"]} />
319
- </Quarter>
320
-
321
- <Quarter position="right" {topHeight} {bottomHeight}>
322
- <Form slot="top-or-left" title="Contact Support" />
323
- <Text slot="bottom-or-right" title="System Status" content="All systems operational..." />
324
- </Quarter>
325
- ```
326
-
327
- ## Trade-offs
328
-
329
- - May require more components than a single grid engine
330
- - Resizing logic coordination may need shared state management
331
- - Nesting complexity for very complex layouts