tuiuiu.js 0.1.1 → 0.1.4-next.64ff654
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +67 -36
- package/dist/atoms/button.d.ts.map +1 -1
- package/dist/atoms/button.js +17 -9
- package/dist/atoms/button.js.map +1 -1
- package/dist/atoms/text-input.d.ts +2 -0
- package/dist/atoms/text-input.d.ts.map +1 -1
- package/dist/atoms/text-input.js +13 -7
- package/dist/atoms/text-input.js.map +1 -1
- package/dist/atoms/tooltip.d.ts.map +1 -1
- package/dist/atoms/tooltip.js +2 -1
- package/dist/atoms/tooltip.js.map +1 -1
- package/dist/cli/commands/help.d.ts +5 -0
- package/dist/cli/commands/help.d.ts.map +1 -0
- package/dist/cli/commands/help.js +31 -0
- package/dist/cli/commands/help.js.map +1 -0
- package/dist/cli/commands/mcp.d.ts +11 -0
- package/dist/cli/commands/mcp.d.ts.map +1 -0
- package/dist/cli/commands/mcp.js +21 -0
- package/dist/cli/commands/mcp.js.map +1 -0
- package/dist/cli/commands/storybook.d.ts +5 -0
- package/dist/cli/commands/storybook.d.ts.map +1 -0
- package/dist/cli/commands/storybook.js +9 -0
- package/dist/cli/commands/storybook.js.map +1 -0
- package/dist/cli/index.d.ts +14 -0
- package/dist/cli/index.d.ts.map +1 -0
- package/dist/cli/index.js +50 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/core/error-boundary.d.ts.map +1 -1
- package/dist/core/error-boundary.js +2 -1
- package/dist/core/error-boundary.js.map +1 -1
- package/dist/core/hotkeys.d.ts +62 -0
- package/dist/core/hotkeys.d.ts.map +1 -0
- package/dist/core/hotkeys.js +0 -0
- package/dist/core/hotkeys.js.map +1 -0
- package/dist/core/index.d.ts +3 -1
- package/dist/core/index.d.ts.map +1 -1
- package/dist/core/index.js +9 -1
- package/dist/core/index.js.map +1 -1
- package/dist/core/screen.d.ts.map +1 -1
- package/dist/core/screen.js +2 -0
- package/dist/core/screen.js.map +1 -1
- package/dist/core/theme.d.ts +79 -0
- package/dist/core/theme.d.ts.map +1 -1
- package/dist/core/theme.js +358 -0
- package/dist/core/theme.js.map +1 -1
- package/dist/design-system/data-display/index.d.ts +9 -6
- package/dist/design-system/data-display/index.d.ts.map +1 -1
- package/dist/design-system/data-display/index.js +16 -7
- package/dist/design-system/data-display/index.js.map +1 -1
- package/dist/design-system/feedback/badge.d.ts +21 -4
- package/dist/design-system/feedback/badge.d.ts.map +1 -1
- package/dist/design-system/feedback/badge.js +15 -2
- package/dist/design-system/feedback/badge.js.map +1 -1
- package/dist/design-system/forms/index.d.ts +11 -8
- package/dist/design-system/forms/index.d.ts.map +1 -1
- package/dist/design-system/forms/index.js +19 -10
- package/dist/design-system/forms/index.js.map +1 -1
- package/dist/design-system/layout/index.d.ts +7 -4
- package/dist/design-system/layout/index.d.ts.map +1 -1
- package/dist/design-system/layout/index.js +18 -6
- package/dist/design-system/layout/index.js.map +1 -1
- package/dist/design-system/media/picture.d.ts.map +1 -1
- package/dist/design-system/media/picture.js +2 -1
- package/dist/design-system/media/picture.js.map +1 -1
- package/dist/design-system/overlays/index.d.ts +6 -3
- package/dist/design-system/overlays/index.d.ts.map +1 -1
- package/dist/design-system/overlays/index.js +9 -3
- package/dist/design-system/overlays/index.js.map +1 -1
- package/dist/design-system/visual/splash-screen.d.ts.map +1 -1
- package/dist/design-system/visual/splash-screen.js +38 -18
- package/dist/design-system/visual/splash-screen.js.map +1 -1
- package/dist/hooks/index.d.ts +2 -0
- package/dist/hooks/index.d.ts.map +1 -1
- package/dist/hooks/index.js +2 -0
- package/dist/hooks/index.js.map +1 -1
- package/dist/hooks/use-hotkeys.d.ts +153 -0
- package/dist/hooks/use-hotkeys.d.ts.map +1 -0
- package/dist/hooks/use-hotkeys.js +379 -0
- package/dist/hooks/use-hotkeys.js.map +1 -0
- package/dist/hooks/use-input.d.ts +2 -10
- package/dist/hooks/use-input.d.ts.map +1 -1
- package/dist/hooks/use-input.js +2 -287
- package/dist/hooks/use-input.js.map +1 -1
- package/dist/hooks/use-mouse.d.ts +5 -0
- package/dist/hooks/use-mouse.d.ts.map +1 -1
- package/dist/hooks/use-mouse.js +29 -11
- package/dist/hooks/use-mouse.js.map +1 -1
- package/dist/index.d.ts +6 -4
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +15 -3
- package/dist/index.js.map +1 -1
- package/dist/mcp/docs-data.d.ts +31 -0
- package/dist/mcp/docs-data.d.ts.map +1 -0
- package/dist/mcp/docs-data.js +637 -0
- package/dist/mcp/docs-data.js.map +1 -0
- package/dist/mcp/index.d.ts +14 -0
- package/dist/mcp/index.d.ts.map +1 -0
- package/dist/mcp/index.js +12 -0
- package/dist/mcp/index.js.map +1 -0
- package/dist/mcp/server.d.ts +31 -0
- package/dist/mcp/server.d.ts.map +1 -0
- package/dist/mcp/server.js +597 -0
- package/dist/mcp/server.js.map +1 -0
- package/dist/mcp/types.d.ts +114 -0
- package/dist/mcp/types.d.ts.map +1 -0
- package/dist/mcp/types.js +16 -0
- package/dist/mcp/types.js.map +1 -0
- package/dist/molecules/autocomplete.d.ts.map +1 -1
- package/dist/molecules/autocomplete.js +2 -1
- package/dist/molecules/autocomplete.js.map +1 -1
- package/dist/molecules/calendar.d.ts.map +1 -1
- package/dist/molecules/calendar.js +5 -3
- package/dist/molecules/calendar.js.map +1 -1
- package/dist/molecules/data-viz/annotations.d.ts +75 -0
- package/dist/molecules/data-viz/annotations.d.ts.map +1 -0
- package/dist/molecules/data-viz/annotations.js +40 -0
- package/dist/molecules/data-viz/annotations.js.map +1 -0
- package/dist/molecules/data-viz/gantt-chart.d.ts +66 -0
- package/dist/molecules/data-viz/gantt-chart.d.ts.map +1 -0
- package/dist/molecules/data-viz/gantt-chart.js +134 -0
- package/dist/molecules/data-viz/gantt-chart.js.map +1 -0
- package/dist/molecules/data-viz/gauge.d.ts +2 -2
- package/dist/molecules/data-viz/gauge.d.ts.map +1 -1
- package/dist/molecules/data-viz/gauge.js +24 -8
- package/dist/molecules/data-viz/gauge.js.map +1 -1
- package/dist/molecules/data-viz/heatmap.d.ts +8 -2
- package/dist/molecules/data-viz/heatmap.d.ts.map +1 -1
- package/dist/molecules/data-viz/heatmap.js +41 -9
- package/dist/molecules/data-viz/heatmap.js.map +1 -1
- package/dist/molecules/data-viz/hooks.d.ts +264 -0
- package/dist/molecules/data-viz/hooks.d.ts.map +1 -0
- package/dist/molecules/data-viz/hooks.js +373 -0
- package/dist/molecules/data-viz/hooks.js.map +1 -0
- package/dist/molecules/data-viz/index.d.ts +14 -0
- package/dist/molecules/data-viz/index.d.ts.map +1 -1
- package/dist/molecules/data-viz/index.js +14 -0
- package/dist/molecules/data-viz/index.js.map +1 -1
- package/dist/molecules/data-viz/legend.d.ts +82 -0
- package/dist/molecules/data-viz/legend.d.ts.map +1 -0
- package/dist/molecules/data-viz/legend.js +146 -0
- package/dist/molecules/data-viz/legend.js.map +1 -0
- package/dist/molecules/data-viz/line-chart.d.ts.map +1 -1
- package/dist/molecules/data-viz/line-chart.js +48 -12
- package/dist/molecules/data-viz/line-chart.js.map +1 -1
- package/dist/molecules/data-viz/radar-chart.d.ts +61 -0
- package/dist/molecules/data-viz/radar-chart.d.ts.map +1 -0
- package/dist/molecules/data-viz/radar-chart.js +86 -0
- package/dist/molecules/data-viz/radar-chart.js.map +1 -0
- package/dist/molecules/data-viz/scatter-plot.d.ts +97 -0
- package/dist/molecules/data-viz/scatter-plot.d.ts.map +1 -0
- package/dist/molecules/data-viz/scatter-plot.js +205 -0
- package/dist/molecules/data-viz/scatter-plot.js.map +1 -0
- package/dist/molecules/data-viz/time-heatmap.d.ts +48 -0
- package/dist/molecules/data-viz/time-heatmap.d.ts.map +1 -0
- package/dist/molecules/data-viz/time-heatmap.js +145 -0
- package/dist/molecules/data-viz/time-heatmap.js.map +1 -0
- package/dist/molecules/select.d.ts +2 -0
- package/dist/molecules/select.d.ts.map +1 -1
- package/dist/molecules/select.js +4 -3
- package/dist/molecules/select.js.map +1 -1
- package/dist/molecules/tabs.d.ts.map +1 -1
- package/dist/molecules/tabs.js +14 -2
- package/dist/molecules/tabs.js.map +1 -1
- package/dist/organisms/command-palette.d.ts.map +1 -1
- package/dist/organisms/command-palette.js +2 -1
- package/dist/organisms/command-palette.js.map +1 -1
- package/dist/storybook/app.d.ts.map +1 -1
- package/dist/storybook/app.js +53 -44
- package/dist/storybook/app.js.map +1 -1
- package/dist/storybook/components/compare-view.d.ts.map +1 -1
- package/dist/storybook/components/compare-view.js +19 -18
- package/dist/storybook/components/compare-view.js.map +1 -1
- package/dist/storybook/components/log-viewer.d.ts.map +1 -1
- package/dist/storybook/components/log-viewer.js +9 -8
- package/dist/storybook/components/log-viewer.js.map +1 -1
- package/dist/storybook/components/preview.d.ts.map +1 -1
- package/dist/storybook/components/preview.js +34 -33
- package/dist/storybook/components/preview.js.map +1 -1
- package/dist/storybook/components/sidebar.d.ts.map +1 -1
- package/dist/storybook/components/sidebar.js +21 -20
- package/dist/storybook/components/sidebar.js.map +1 -1
- package/dist/storybook/stories/apps/index.d.ts.map +1 -1
- package/dist/storybook/stories/apps/index.js +306 -209
- package/dist/storybook/stories/apps/index.js.map +1 -1
- package/dist/storybook/stories/atoms/index.d.ts.map +1 -1
- package/dist/storybook/stories/atoms/index.js.map +1 -1
- package/dist/storybook/stories/molecules/index.d.ts +25 -0
- package/dist/storybook/stories/molecules/index.d.ts.map +1 -1
- package/dist/storybook/stories/molecules/index.js +402 -20
- package/dist/storybook/stories/molecules/index.js.map +1 -1
- package/dist/storybook/stories/organisms/index.d.ts.map +1 -1
- package/dist/storybook/stories/organisms/index.js +1 -1
- package/dist/storybook/stories/organisms/index.js.map +1 -1
- package/dist/utils/index.d.ts +2 -0
- package/dist/utils/index.d.ts.map +1 -1
- package/dist/utils/index.js +2 -0
- package/dist/utils/index.js.map +1 -1
- package/dist/utils/system-data.d.ts +73 -0
- package/dist/utils/system-data.d.ts.map +1 -0
- package/dist/utils/system-data.js +367 -0
- package/dist/utils/system-data.js.map +1 -0
- package/dist/version.d.ts +43 -0
- package/dist/version.d.ts.map +1 -0
- package/dist/version.js +82 -0
- package/dist/version.js.map +1 -0
- package/package.json +22 -22
- package/dist/components/canvas.d.ts +0 -322
- package/dist/components/canvas.d.ts.map +0 -1
- package/dist/components/canvas.js +0 -833
- package/dist/components/canvas.js.map +0 -1
- package/dist/components/code-block.d.ts +0 -75
- package/dist/components/code-block.d.ts.map +0 -1
- package/dist/components/code-block.js +0 -322
- package/dist/components/code-block.js.map +0 -1
- package/dist/components/components.d.ts +0 -122
- package/dist/components/components.d.ts.map +0 -1
- package/dist/components/components.js +0 -151
- package/dist/components/components.js.map +0 -1
- package/dist/components/data-viz/bar-chart.d.ts +0 -167
- package/dist/components/data-viz/bar-chart.d.ts.map +0 -1
- package/dist/components/data-viz/bar-chart.js +0 -375
- package/dist/components/data-viz/bar-chart.js.map +0 -1
- package/dist/components/data-viz/gauge.d.ts +0 -163
- package/dist/components/data-viz/gauge.d.ts.map +0 -1
- package/dist/components/data-viz/gauge.js +0 -451
- package/dist/components/data-viz/gauge.js.map +0 -1
- package/dist/components/data-viz/heatmap.d.ts +0 -154
- package/dist/components/data-viz/heatmap.d.ts.map +0 -1
- package/dist/components/data-viz/heatmap.js +0 -458
- package/dist/components/data-viz/heatmap.js.map +0 -1
- package/dist/components/data-viz/index.d.ts +0 -16
- package/dist/components/data-viz/index.d.ts.map +0 -1
- package/dist/components/data-viz/index.js +0 -16
- package/dist/components/data-viz/index.js.map +0 -1
- package/dist/components/data-viz/line-chart.d.ts +0 -157
- package/dist/components/data-viz/line-chart.d.ts.map +0 -1
- package/dist/components/data-viz/line-chart.js +0 -578
- package/dist/components/data-viz/line-chart.js.map +0 -1
- package/dist/components/data-viz/sparkline.d.ts +0 -156
- package/dist/components/data-viz/sparkline.d.ts.map +0 -1
- package/dist/components/data-viz/sparkline.js +0 -325
- package/dist/components/data-viz/sparkline.js.map +0 -1
- package/dist/components/grid.d.ts +0 -234
- package/dist/components/grid.d.ts.map +0 -1
- package/dist/components/grid.js +0 -719
- package/dist/components/grid.js.map +0 -1
- package/dist/components/index.d.ts +0 -33
- package/dist/components/index.d.ts.map +0 -1
- package/dist/components/index.js +0 -69
- package/dist/components/index.js.map +0 -1
- package/dist/components/markdown.d.ts +0 -52
- package/dist/components/markdown.d.ts.map +0 -1
- package/dist/components/markdown.js +0 -341
- package/dist/components/markdown.js.map +0 -1
- package/dist/components/modal.d.ts +0 -237
- package/dist/components/modal.d.ts.map +0 -1
- package/dist/components/modal.js +0 -396
- package/dist/components/modal.js.map +0 -1
- package/dist/components/progress-bar.d.ts +0 -89
- package/dist/components/progress-bar.d.ts.map +0 -1
- package/dist/components/progress-bar.js +0 -288
- package/dist/components/progress-bar.js.map +0 -1
- package/dist/components/select.d.ts +0 -114
- package/dist/components/select.d.ts.map +0 -1
- package/dist/components/select.js +0 -415
- package/dist/components/select.js.map +0 -1
- package/dist/components/spinner.d.ts +0 -71
- package/dist/components/spinner.d.ts.map +0 -1
- package/dist/components/spinner.js +0 -300
- package/dist/components/spinner.js.map +0 -1
- package/dist/components/split-panel.d.ts +0 -175
- package/dist/components/split-panel.d.ts.map +0 -1
- package/dist/components/split-panel.js +0 -322
- package/dist/components/split-panel.js.map +0 -1
- package/dist/components/table.d.ts +0 -103
- package/dist/components/table.d.ts.map +0 -1
- package/dist/components/table.js +0 -359
- package/dist/components/table.js.map +0 -1
- package/dist/components/text-input.d.ts +0 -79
- package/dist/components/text-input.d.ts.map +0 -1
- package/dist/components/text-input.js +0 -332
- package/dist/components/text-input.js.map +0 -1
- package/dist/design-system/data-display/calendar.d.ts +0 -141
- package/dist/design-system/data-display/calendar.d.ts.map +0 -1
- package/dist/design-system/data-display/calendar.js +0 -524
- package/dist/design-system/data-display/calendar.js.map +0 -1
- package/dist/design-system/data-display/code-block.d.ts +0 -75
- package/dist/design-system/data-display/code-block.d.ts.map +0 -1
- package/dist/design-system/data-display/code-block.js +0 -311
- package/dist/design-system/data-display/code-block.js.map +0 -1
- package/dist/design-system/data-display/data-table.d.ts +0 -173
- package/dist/design-system/data-display/data-table.d.ts.map +0 -1
- package/dist/design-system/data-display/data-table.js +0 -428
- package/dist/design-system/data-display/data-table.js.map +0 -1
- package/dist/design-system/data-display/markdown.d.ts +0 -52
- package/dist/design-system/data-display/markdown.d.ts.map +0 -1
- package/dist/design-system/data-display/markdown.js +0 -341
- package/dist/design-system/data-display/markdown.js.map +0 -1
- package/dist/design-system/data-display/table.d.ts +0 -103
- package/dist/design-system/data-display/table.d.ts.map +0 -1
- package/dist/design-system/data-display/table.js +0 -342
- package/dist/design-system/data-display/table.js.map +0 -1
- package/dist/design-system/data-display/tree.d.ts +0 -166
- package/dist/design-system/data-display/tree.d.ts.map +0 -1
- package/dist/design-system/data-display/tree.js +0 -428
- package/dist/design-system/data-display/tree.js.map +0 -1
- package/dist/design-system/forms/autocomplete.d.ts +0 -163
- package/dist/design-system/forms/autocomplete.d.ts.map +0 -1
- package/dist/design-system/forms/autocomplete.js +0 -455
- package/dist/design-system/forms/autocomplete.js.map +0 -1
- package/dist/design-system/forms/button.d.ts +0 -106
- package/dist/design-system/forms/button.d.ts.map +0 -1
- package/dist/design-system/forms/button.js +0 -170
- package/dist/design-system/forms/button.js.map +0 -1
- package/dist/design-system/forms/multi-select.d.ts +0 -102
- package/dist/design-system/forms/multi-select.d.ts.map +0 -1
- package/dist/design-system/forms/multi-select.js +0 -309
- package/dist/design-system/forms/multi-select.js.map +0 -1
- package/dist/design-system/forms/radio-group.d.ts +0 -88
- package/dist/design-system/forms/radio-group.d.ts.map +0 -1
- package/dist/design-system/forms/radio-group.js +0 -145
- package/dist/design-system/forms/radio-group.js.map +0 -1
- package/dist/design-system/forms/select.d.ts +0 -116
- package/dist/design-system/forms/select.d.ts.map +0 -1
- package/dist/design-system/forms/select.js +0 -441
- package/dist/design-system/forms/select.js.map +0 -1
- package/dist/design-system/forms/slider.d.ts +0 -134
- package/dist/design-system/forms/slider.d.ts.map +0 -1
- package/dist/design-system/forms/slider.js +0 -314
- package/dist/design-system/forms/slider.js.map +0 -1
- package/dist/design-system/forms/switch.d.ts +0 -99
- package/dist/design-system/forms/switch.d.ts.map +0 -1
- package/dist/design-system/forms/switch.js +0 -173
- package/dist/design-system/forms/switch.js.map +0 -1
- package/dist/design-system/forms/text-input.d.ts +0 -79
- package/dist/design-system/forms/text-input.d.ts.map +0 -1
- package/dist/design-system/forms/text-input.js +0 -344
- package/dist/design-system/forms/text-input.js.map +0 -1
- package/dist/design-system/layout/collapsible.d.ts +0 -166
- package/dist/design-system/layout/collapsible.d.ts.map +0 -1
- package/dist/design-system/layout/collapsible.js +0 -286
- package/dist/design-system/layout/collapsible.js.map +0 -1
- package/dist/design-system/layout/scroll-area.d.ts +0 -188
- package/dist/design-system/layout/scroll-area.d.ts.map +0 -1
- package/dist/design-system/layout/scroll-area.js +0 -348
- package/dist/design-system/layout/scroll-area.js.map +0 -1
- package/dist/design-system/layout/split-panel.d.ts +0 -183
- package/dist/design-system/layout/split-panel.d.ts.map +0 -1
- package/dist/design-system/layout/split-panel.js +0 -323
- package/dist/design-system/layout/split-panel.js.map +0 -1
- package/dist/design-system/layout/tabs.d.ts +0 -129
- package/dist/design-system/layout/tabs.d.ts.map +0 -1
- package/dist/design-system/layout/tabs.js +0 -373
- package/dist/design-system/layout/tabs.js.map +0 -1
- package/dist/design-system/overlays/command-palette.d.ts +0 -217
- package/dist/design-system/overlays/command-palette.d.ts.map +0 -1
- package/dist/design-system/overlays/command-palette.js +0 -443
- package/dist/design-system/overlays/command-palette.js.map +0 -1
- package/dist/design-system/overlays/modal.d.ts +0 -251
- package/dist/design-system/overlays/modal.d.ts.map +0 -1
- package/dist/design-system/overlays/modal.js +0 -461
- package/dist/design-system/overlays/modal.js.map +0 -1
- package/dist/design-system/overlays/overlay-stack.d.ts +0 -200
- package/dist/design-system/overlays/overlay-stack.d.ts.map +0 -1
- package/dist/design-system/overlays/overlay-stack.js +0 -341
- package/dist/design-system/overlays/overlay-stack.js.map +0 -1
- package/dist/design-system/primitives/box.d.ts +0 -16
- package/dist/design-system/primitives/box.d.ts.map +0 -1
- package/dist/design-system/primitives/box.js +0 -23
- package/dist/design-system/primitives/box.js.map +0 -1
- package/dist/design-system/primitives/divider.d.ts +0 -52
- package/dist/design-system/primitives/divider.d.ts.map +0 -1
- package/dist/design-system/primitives/divider.js +0 -72
- package/dist/design-system/primitives/divider.js.map +0 -1
- package/dist/design-system/primitives/helpers.d.ts +0 -10
- package/dist/design-system/primitives/helpers.d.ts.map +0 -1
- package/dist/design-system/primitives/helpers.js +0 -27
- package/dist/design-system/primitives/helpers.js.map +0 -1
- package/dist/design-system/primitives/index.d.ts +0 -11
- package/dist/design-system/primitives/index.d.ts.map +0 -1
- package/dist/design-system/primitives/index.js +0 -14
- package/dist/design-system/primitives/index.js.map +0 -1
- package/dist/design-system/primitives/slot.d.ts +0 -35
- package/dist/design-system/primitives/slot.d.ts.map +0 -1
- package/dist/design-system/primitives/slot.js +0 -17
- package/dist/design-system/primitives/slot.js.map +0 -1
- package/dist/design-system/primitives/spacer.d.ts +0 -34
- package/dist/design-system/primitives/spacer.d.ts.map +0 -1
- package/dist/design-system/primitives/spacer.js +0 -53
- package/dist/design-system/primitives/spacer.js.map +0 -1
- package/dist/design-system/primitives/text.d.ts +0 -12
- package/dist/design-system/primitives/text.d.ts.map +0 -1
- package/dist/design-system/primitives/text.js +0 -25
- package/dist/design-system/primitives/text.js.map +0 -1
- package/dist/design-system/primitives/utilities.d.ts +0 -70
- package/dist/design-system/primitives/utilities.d.ts.map +0 -1
- package/dist/design-system/primitives/utilities.js +0 -56
- package/dist/design-system/primitives/utilities.js.map +0 -1
- package/dist/storybook/cli.d.ts +0 -10
- package/dist/storybook/cli.d.ts.map +0 -1
- package/dist/storybook/cli.js +0 -14
- package/dist/storybook/cli.js.map +0 -1
package/dist/components/grid.js
DELETED
|
@@ -1,719 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Grid Layout System
|
|
3
|
-
*
|
|
4
|
-
* CSS Grid-inspired layout for terminal UIs.
|
|
5
|
-
* Supports:
|
|
6
|
-
* - Template-based grid definition (rows/columns)
|
|
7
|
-
* - Named areas
|
|
8
|
-
* - Gap control
|
|
9
|
-
* - Auto-placement
|
|
10
|
-
* - Span across cells
|
|
11
|
-
* - Alignment (justify/align items)
|
|
12
|
-
*
|
|
13
|
-
* @example
|
|
14
|
-
* ```typescript
|
|
15
|
-
* Grid({
|
|
16
|
-
* columns: '1fr 2fr 1fr',
|
|
17
|
-
* rows: 'auto 1fr auto',
|
|
18
|
-
* gap: 1,
|
|
19
|
-
* areas: `
|
|
20
|
-
* "header header header"
|
|
21
|
-
* "nav main aside"
|
|
22
|
-
* "footer footer footer"
|
|
23
|
-
* `,
|
|
24
|
-
* },
|
|
25
|
-
* GridItem({ area: 'header' }, Text({}, 'Header')),
|
|
26
|
-
* GridItem({ area: 'nav' }, Text({}, 'Nav')),
|
|
27
|
-
* GridItem({ area: 'main' }, Text({}, 'Main')),
|
|
28
|
-
* GridItem({ area: 'aside' }, Text({}, 'Aside')),
|
|
29
|
-
* GridItem({ area: 'footer' }, Text({}, 'Footer'))
|
|
30
|
-
* )
|
|
31
|
-
* ```
|
|
32
|
-
*/
|
|
33
|
-
import { Box } from '../primitives/index.js';
|
|
34
|
-
// =============================================================================
|
|
35
|
-
// Track Parsing
|
|
36
|
-
// =============================================================================
|
|
37
|
-
/**
|
|
38
|
-
* Parse a track size string into structured format
|
|
39
|
-
*/
|
|
40
|
-
export function parseTrackSize(size) {
|
|
41
|
-
if (typeof size === 'number') {
|
|
42
|
-
return { type: 'fixed', value: size };
|
|
43
|
-
}
|
|
44
|
-
if (size === 'auto') {
|
|
45
|
-
return { type: 'auto', value: 0 };
|
|
46
|
-
}
|
|
47
|
-
if (size === 'min-content') {
|
|
48
|
-
return { type: 'min-content', value: 0 };
|
|
49
|
-
}
|
|
50
|
-
if (size === 'max-content') {
|
|
51
|
-
return { type: 'max-content', value: 0 };
|
|
52
|
-
}
|
|
53
|
-
// Check for pure numeric string (fixed size)
|
|
54
|
-
const numericMatch = size.match(/^(\d+(?:\.\d+)?)$/);
|
|
55
|
-
if (numericMatch) {
|
|
56
|
-
return { type: 'fixed', value: parseFloat(numericMatch[1]) };
|
|
57
|
-
}
|
|
58
|
-
// Check for fr unit
|
|
59
|
-
const frMatch = size.match(/^(\d+(?:\.\d+)?)fr$/);
|
|
60
|
-
if (frMatch) {
|
|
61
|
-
return { type: 'fr', value: parseFloat(frMatch[1]) };
|
|
62
|
-
}
|
|
63
|
-
// Check for minmax - allow optional spaces around comma
|
|
64
|
-
const minmaxMatch = size.match(/^minmax\(\s*([^,]+?)\s*,\s*([^)]+?)\s*\)$/);
|
|
65
|
-
if (minmaxMatch) {
|
|
66
|
-
const minTrack = parseTrackSize(minmaxMatch[1].trim());
|
|
67
|
-
const maxTrack = parseTrackSize(minmaxMatch[2].trim());
|
|
68
|
-
return {
|
|
69
|
-
type: 'minmax',
|
|
70
|
-
value: 0,
|
|
71
|
-
min: minTrack.type === 'fixed' ? minTrack.value : 0,
|
|
72
|
-
max: maxTrack.type === 'fixed' ? maxTrack.value : Infinity,
|
|
73
|
-
};
|
|
74
|
-
}
|
|
75
|
-
// Default to auto
|
|
76
|
-
return { type: 'auto', value: 0 };
|
|
77
|
-
}
|
|
78
|
-
/**
|
|
79
|
-
* Parse track definition string into array
|
|
80
|
-
* e.g., '1fr 2fr 1fr' -> [{ type: 'fr', value: 1 }, ...]
|
|
81
|
-
*/
|
|
82
|
-
export function parseTrackDefinition(definition) {
|
|
83
|
-
if (Array.isArray(definition)) {
|
|
84
|
-
return definition.map(parseTrackSize);
|
|
85
|
-
}
|
|
86
|
-
// Handle repeat() function
|
|
87
|
-
const repeatMatch = definition.match(/repeat\((\d+),\s*([^)]+)\)/);
|
|
88
|
-
if (repeatMatch) {
|
|
89
|
-
const count = parseInt(repeatMatch[1], 10);
|
|
90
|
-
const trackDef = repeatMatch[2].trim();
|
|
91
|
-
const parsed = parseTrackSize(trackDef);
|
|
92
|
-
const result = [];
|
|
93
|
-
for (let i = 0; i < count; i++) {
|
|
94
|
-
result.push({ ...parsed });
|
|
95
|
-
}
|
|
96
|
-
// Replace repeat() with expansion and continue parsing
|
|
97
|
-
const expanded = definition.replace(/repeat\(\d+,\s*[^)]+\)/, result.map(() => trackDef).join(' '));
|
|
98
|
-
return parseTrackDefinition(expanded);
|
|
99
|
-
}
|
|
100
|
-
// Split by whitespace
|
|
101
|
-
const parts = definition.trim().split(/\s+/);
|
|
102
|
-
return parts.map((part) => parseTrackSize(part));
|
|
103
|
-
}
|
|
104
|
-
/**
|
|
105
|
-
* Parse grid-template-areas string
|
|
106
|
-
*/
|
|
107
|
-
export function parseGridAreas(areasTemplate) {
|
|
108
|
-
const areas = new Map();
|
|
109
|
-
const rows = areasTemplate
|
|
110
|
-
.trim()
|
|
111
|
-
.split('\n')
|
|
112
|
-
.map((row) => row
|
|
113
|
-
.trim()
|
|
114
|
-
.replace(/^["']|["']$/g, '')
|
|
115
|
-
.split(/\s+/));
|
|
116
|
-
// Track area positions
|
|
117
|
-
const areaPositions = new Map();
|
|
118
|
-
for (let rowIndex = 0; rowIndex < rows.length; rowIndex++) {
|
|
119
|
-
const row = rows[rowIndex];
|
|
120
|
-
for (let colIndex = 0; colIndex < row.length; colIndex++) {
|
|
121
|
-
const name = row[colIndex];
|
|
122
|
-
if (name === '.')
|
|
123
|
-
continue; // Empty cell
|
|
124
|
-
const existing = areaPositions.get(name);
|
|
125
|
-
if (existing) {
|
|
126
|
-
existing.minRow = Math.min(existing.minRow, rowIndex);
|
|
127
|
-
existing.maxRow = Math.max(existing.maxRow, rowIndex);
|
|
128
|
-
existing.minCol = Math.min(existing.minCol, colIndex);
|
|
129
|
-
existing.maxCol = Math.max(existing.maxCol, colIndex);
|
|
130
|
-
}
|
|
131
|
-
else {
|
|
132
|
-
areaPositions.set(name, {
|
|
133
|
-
minRow: rowIndex,
|
|
134
|
-
maxRow: rowIndex,
|
|
135
|
-
minCol: colIndex,
|
|
136
|
-
maxCol: colIndex,
|
|
137
|
-
});
|
|
138
|
-
}
|
|
139
|
-
}
|
|
140
|
-
}
|
|
141
|
-
// Convert to GridArea (1-based indices)
|
|
142
|
-
for (const [name, pos] of areaPositions) {
|
|
143
|
-
areas.set(name, {
|
|
144
|
-
name,
|
|
145
|
-
rowStart: pos.minRow + 1,
|
|
146
|
-
rowEnd: pos.maxRow + 2,
|
|
147
|
-
colStart: pos.minCol + 1,
|
|
148
|
-
colEnd: pos.maxCol + 2,
|
|
149
|
-
});
|
|
150
|
-
}
|
|
151
|
-
return areas;
|
|
152
|
-
}
|
|
153
|
-
// =============================================================================
|
|
154
|
-
// Track Size Calculation
|
|
155
|
-
// =============================================================================
|
|
156
|
-
/**
|
|
157
|
-
* Calculate track sizes given available space
|
|
158
|
-
*/
|
|
159
|
-
export function calculateTrackSizes(tracks, availableSpace, gap, contentSizes) {
|
|
160
|
-
const sizes = new Array(tracks.length).fill(0);
|
|
161
|
-
const totalGaps = Math.max(0, tracks.length - 1) * gap;
|
|
162
|
-
let remainingSpace = availableSpace - totalGaps;
|
|
163
|
-
let totalFr = 0;
|
|
164
|
-
// First pass: calculate fixed and content-based sizes
|
|
165
|
-
for (let i = 0; i < tracks.length; i++) {
|
|
166
|
-
const track = tracks[i];
|
|
167
|
-
switch (track.type) {
|
|
168
|
-
case 'fixed':
|
|
169
|
-
sizes[i] = track.value;
|
|
170
|
-
remainingSpace -= track.value;
|
|
171
|
-
break;
|
|
172
|
-
case 'auto':
|
|
173
|
-
case 'min-content':
|
|
174
|
-
case 'max-content':
|
|
175
|
-
sizes[i] = contentSizes[i] || 0;
|
|
176
|
-
remainingSpace -= sizes[i];
|
|
177
|
-
break;
|
|
178
|
-
case 'minmax':
|
|
179
|
-
// Start with minimum
|
|
180
|
-
sizes[i] = track.min || 0;
|
|
181
|
-
remainingSpace -= sizes[i];
|
|
182
|
-
break;
|
|
183
|
-
case 'fr':
|
|
184
|
-
totalFr += track.value;
|
|
185
|
-
break;
|
|
186
|
-
}
|
|
187
|
-
}
|
|
188
|
-
// Second pass: distribute remaining space to fr units
|
|
189
|
-
if (totalFr > 0 && remainingSpace > 0) {
|
|
190
|
-
const frSize = remainingSpace / totalFr;
|
|
191
|
-
for (let i = 0; i < tracks.length; i++) {
|
|
192
|
-
const track = tracks[i];
|
|
193
|
-
if (track.type === 'fr') {
|
|
194
|
-
sizes[i] = Math.floor(frSize * track.value);
|
|
195
|
-
}
|
|
196
|
-
}
|
|
197
|
-
}
|
|
198
|
-
// Third pass: handle minmax expansion
|
|
199
|
-
for (let i = 0; i < tracks.length; i++) {
|
|
200
|
-
const track = tracks[i];
|
|
201
|
-
if (track.type === 'minmax' && track.max !== undefined) {
|
|
202
|
-
const maxSize = track.max === Infinity ? availableSpace : track.max;
|
|
203
|
-
// Could expand minmax tracks if there's leftover space
|
|
204
|
-
// For simplicity, we'll leave them at their minimum for now
|
|
205
|
-
sizes[i] = Math.min(Math.max(sizes[i], track.min || 0), maxSize);
|
|
206
|
-
}
|
|
207
|
-
}
|
|
208
|
-
// Ensure no negative sizes
|
|
209
|
-
return sizes.map((s) => Math.max(0, s));
|
|
210
|
-
}
|
|
211
|
-
// =============================================================================
|
|
212
|
-
// Item Placement
|
|
213
|
-
// =============================================================================
|
|
214
|
-
/** Parse grid-column or grid-row shorthand */
|
|
215
|
-
function parseLineSpec(spec, defaultStart, trackCount) {
|
|
216
|
-
if (spec === undefined) {
|
|
217
|
-
return { start: defaultStart, end: defaultStart + 1 };
|
|
218
|
-
}
|
|
219
|
-
if (typeof spec === 'number') {
|
|
220
|
-
return { start: spec, end: spec + 1 };
|
|
221
|
-
}
|
|
222
|
-
// Handle 'span N'
|
|
223
|
-
const spanMatch = spec.match(/^span\s+(\d+)$/);
|
|
224
|
-
if (spanMatch) {
|
|
225
|
-
const span = parseInt(spanMatch[1], 10);
|
|
226
|
-
return { start: defaultStart, end: defaultStart + span };
|
|
227
|
-
}
|
|
228
|
-
// Handle 'start / end'
|
|
229
|
-
const rangeMatch = spec.match(/^(\d+)\s*\/\s*(\d+)$/);
|
|
230
|
-
if (rangeMatch) {
|
|
231
|
-
return {
|
|
232
|
-
start: parseInt(rangeMatch[1], 10),
|
|
233
|
-
end: parseInt(rangeMatch[2], 10),
|
|
234
|
-
};
|
|
235
|
-
}
|
|
236
|
-
// Handle 'start / span N'
|
|
237
|
-
const startSpanMatch = spec.match(/^(\d+)\s*\/\s*span\s+(\d+)$/);
|
|
238
|
-
if (startSpanMatch) {
|
|
239
|
-
const start = parseInt(startSpanMatch[1], 10);
|
|
240
|
-
const span = parseInt(startSpanMatch[2], 10);
|
|
241
|
-
return { start, end: start + span };
|
|
242
|
-
}
|
|
243
|
-
return { start: defaultStart, end: defaultStart + 1 };
|
|
244
|
-
}
|
|
245
|
-
/**
|
|
246
|
-
* Calculate cell position for a grid item
|
|
247
|
-
*/
|
|
248
|
-
export function calculateCellPosition(options, areas, columnCount, rowCount, autoPlacement) {
|
|
249
|
-
// Check for named area
|
|
250
|
-
if (options.area) {
|
|
251
|
-
const area = areas.get(options.area);
|
|
252
|
-
if (area) {
|
|
253
|
-
return {
|
|
254
|
-
row: area.rowStart,
|
|
255
|
-
column: area.colStart,
|
|
256
|
-
rowSpan: area.rowEnd - area.rowStart,
|
|
257
|
-
columnSpan: area.colEnd - area.colStart,
|
|
258
|
-
};
|
|
259
|
-
}
|
|
260
|
-
}
|
|
261
|
-
// Parse column spec
|
|
262
|
-
const colSpec = parseLineSpec(options.column ?? options.columnStart, autoPlacement.column, columnCount);
|
|
263
|
-
if (options.columnEnd !== undefined) {
|
|
264
|
-
colSpec.end = options.columnEnd;
|
|
265
|
-
}
|
|
266
|
-
if (options.columnSpan !== undefined) {
|
|
267
|
-
colSpec.end = colSpec.start + options.columnSpan;
|
|
268
|
-
}
|
|
269
|
-
// Parse row spec
|
|
270
|
-
const rowSpec = parseLineSpec(options.row ?? options.rowStart, autoPlacement.row, rowCount);
|
|
271
|
-
if (options.rowEnd !== undefined) {
|
|
272
|
-
rowSpec.end = options.rowEnd;
|
|
273
|
-
}
|
|
274
|
-
if (options.rowSpan !== undefined) {
|
|
275
|
-
rowSpec.end = rowSpec.start + options.rowSpan;
|
|
276
|
-
}
|
|
277
|
-
return {
|
|
278
|
-
row: rowSpec.start,
|
|
279
|
-
column: colSpec.start,
|
|
280
|
-
rowSpan: rowSpec.end - rowSpec.start,
|
|
281
|
-
columnSpan: colSpec.end - colSpec.start,
|
|
282
|
-
};
|
|
283
|
-
}
|
|
284
|
-
// =============================================================================
|
|
285
|
-
// Grid Layout Calculation
|
|
286
|
-
// =============================================================================
|
|
287
|
-
/**
|
|
288
|
-
* Calculate complete grid layout
|
|
289
|
-
*/
|
|
290
|
-
export function calculateGridLayout(options, items, containerWidth, containerHeight) {
|
|
291
|
-
// Parse column and row definitions
|
|
292
|
-
const columns = options.columns
|
|
293
|
-
? parseTrackDefinition(options.columns)
|
|
294
|
-
: [{ type: 'fr', value: 1 }];
|
|
295
|
-
const rows = options.rows
|
|
296
|
-
? parseTrackDefinition(options.rows)
|
|
297
|
-
: items.map(() => ({ type: 'auto', value: 0 }));
|
|
298
|
-
// Parse areas
|
|
299
|
-
const areas = options.areas ? parseGridAreas(options.areas) : new Map();
|
|
300
|
-
// Calculate gaps
|
|
301
|
-
let rowGap = options.rowGap ?? 0;
|
|
302
|
-
let columnGap = options.columnGap ?? 0;
|
|
303
|
-
if (options.gap !== undefined) {
|
|
304
|
-
if (Array.isArray(options.gap)) {
|
|
305
|
-
[rowGap, columnGap] = options.gap;
|
|
306
|
-
}
|
|
307
|
-
else {
|
|
308
|
-
rowGap = columnGap = options.gap;
|
|
309
|
-
}
|
|
310
|
-
}
|
|
311
|
-
// Adjust for border/padding
|
|
312
|
-
const borderOffset = options.border ? 2 : 0;
|
|
313
|
-
const paddingOffset = (options.padding ?? 0) * 2;
|
|
314
|
-
const effectiveWidth = containerWidth - borderOffset - paddingOffset;
|
|
315
|
-
// Calculate column sizes (content sizes not yet known, use 0)
|
|
316
|
-
const contentColSizes = new Array(columns.length).fill(0);
|
|
317
|
-
const columnSizes = calculateTrackSizes(columns, effectiveWidth, columnGap, contentColSizes);
|
|
318
|
-
// Auto-placement cursor
|
|
319
|
-
const autoPlacement = { row: 1, column: 1 };
|
|
320
|
-
const isDense = options.autoFlow?.includes('dense') ?? false;
|
|
321
|
-
const isColumnFlow = options.autoFlow?.includes('column') ?? false;
|
|
322
|
-
// Track occupied cells
|
|
323
|
-
const occupied = new Set();
|
|
324
|
-
// Place items
|
|
325
|
-
const cells = new Map();
|
|
326
|
-
// Sort by order if specified
|
|
327
|
-
const sortedItems = [...items].sort((a, b) => (a.options.order ?? 0) - (b.options.order ?? 0));
|
|
328
|
-
// First pass: place explicitly positioned items
|
|
329
|
-
for (const item of sortedItems) {
|
|
330
|
-
if (item.options.area ||
|
|
331
|
-
item.options.column !== undefined ||
|
|
332
|
-
item.options.row !== undefined ||
|
|
333
|
-
item.options.columnStart !== undefined ||
|
|
334
|
-
item.options.rowStart !== undefined) {
|
|
335
|
-
const position = calculateCellPosition(item.options, areas, columns.length, rows.length, autoPlacement);
|
|
336
|
-
cells.set(item.node, position);
|
|
337
|
-
// Mark cells as occupied
|
|
338
|
-
for (let r = position.row; r < position.row + position.rowSpan; r++) {
|
|
339
|
-
for (let c = position.column; c < position.column + position.columnSpan; c++) {
|
|
340
|
-
occupied.add(`${r},${c}`);
|
|
341
|
-
}
|
|
342
|
-
}
|
|
343
|
-
}
|
|
344
|
-
}
|
|
345
|
-
// Second pass: auto-place remaining items
|
|
346
|
-
for (const item of sortedItems) {
|
|
347
|
-
if (cells.has(item.node))
|
|
348
|
-
continue;
|
|
349
|
-
// Find next available position
|
|
350
|
-
if (isDense) {
|
|
351
|
-
// Dense: start from beginning each time
|
|
352
|
-
autoPlacement.row = 1;
|
|
353
|
-
autoPlacement.column = 1;
|
|
354
|
-
}
|
|
355
|
-
// Find first available cell
|
|
356
|
-
let placed = false;
|
|
357
|
-
const maxRows = Math.max(rows.length, 100); // Limit search
|
|
358
|
-
const maxCols = columns.length;
|
|
359
|
-
outer: for (let r = autoPlacement.row; r <= maxRows && !placed; r++) {
|
|
360
|
-
const startCol = r === autoPlacement.row ? autoPlacement.column : 1;
|
|
361
|
-
for (let c = startCol; c <= maxCols && !placed; c++) {
|
|
362
|
-
if (!occupied.has(`${r},${c}`)) {
|
|
363
|
-
cells.set(item.node, {
|
|
364
|
-
row: r,
|
|
365
|
-
column: c,
|
|
366
|
-
rowSpan: 1,
|
|
367
|
-
columnSpan: 1,
|
|
368
|
-
});
|
|
369
|
-
occupied.add(`${r},${c}`);
|
|
370
|
-
// Update cursor
|
|
371
|
-
if (isColumnFlow) {
|
|
372
|
-
autoPlacement.row = r + 1;
|
|
373
|
-
if (autoPlacement.row > maxRows) {
|
|
374
|
-
autoPlacement.row = 1;
|
|
375
|
-
autoPlacement.column = c + 1;
|
|
376
|
-
}
|
|
377
|
-
}
|
|
378
|
-
else {
|
|
379
|
-
autoPlacement.column = c + 1;
|
|
380
|
-
if (autoPlacement.column > maxCols) {
|
|
381
|
-
autoPlacement.column = 1;
|
|
382
|
-
autoPlacement.row = r + 1;
|
|
383
|
-
}
|
|
384
|
-
}
|
|
385
|
-
placed = true;
|
|
386
|
-
break outer;
|
|
387
|
-
}
|
|
388
|
-
}
|
|
389
|
-
}
|
|
390
|
-
}
|
|
391
|
-
// Determine actual row count
|
|
392
|
-
let maxRow = rows.length;
|
|
393
|
-
for (const pos of cells.values()) {
|
|
394
|
-
maxRow = Math.max(maxRow, pos.row + pos.rowSpan - 1);
|
|
395
|
-
}
|
|
396
|
-
// Extend rows array if needed
|
|
397
|
-
const autoRowTrack = options.autoRows
|
|
398
|
-
? parseTrackSize(options.autoRows)
|
|
399
|
-
: { type: 'auto', value: 0 };
|
|
400
|
-
while (rows.length < maxRow) {
|
|
401
|
-
rows.push({ ...autoRowTrack });
|
|
402
|
-
}
|
|
403
|
-
// Calculate row sizes
|
|
404
|
-
const contentRowSizes = new Array(rows.length).fill(1); // Default to 1 for now
|
|
405
|
-
const effectiveHeight = containerHeight ? containerHeight - borderOffset - paddingOffset : 100;
|
|
406
|
-
const rowSizes = calculateTrackSizes(rows, effectiveHeight, rowGap, contentRowSizes);
|
|
407
|
-
return {
|
|
408
|
-
columnSizes,
|
|
409
|
-
rowSizes,
|
|
410
|
-
cells,
|
|
411
|
-
areas,
|
|
412
|
-
};
|
|
413
|
-
}
|
|
414
|
-
// =============================================================================
|
|
415
|
-
// Grid Components
|
|
416
|
-
// =============================================================================
|
|
417
|
-
/** Grid item data attached to nodes */
|
|
418
|
-
const gridItemData = new WeakMap();
|
|
419
|
-
/**
|
|
420
|
-
* Grid container component
|
|
421
|
-
*/
|
|
422
|
-
export function Grid(options, ...children) {
|
|
423
|
-
const validChildren = children.filter((c) => c !== null);
|
|
424
|
-
// Extract item options
|
|
425
|
-
const items = validChildren.map((node) => ({
|
|
426
|
-
node,
|
|
427
|
-
options: gridItemData.get(node) || {},
|
|
428
|
-
}));
|
|
429
|
-
// Calculate layout
|
|
430
|
-
const containerWidth = options.width ?? 80;
|
|
431
|
-
const layout = calculateGridLayout(options, items, containerWidth, options.height);
|
|
432
|
-
// Calculate gaps
|
|
433
|
-
let rowGap = options.rowGap ?? 0;
|
|
434
|
-
let columnGap = options.columnGap ?? 0;
|
|
435
|
-
if (options.gap !== undefined) {
|
|
436
|
-
if (Array.isArray(options.gap)) {
|
|
437
|
-
[rowGap, columnGap] = options.gap;
|
|
438
|
-
}
|
|
439
|
-
else {
|
|
440
|
-
rowGap = columnGap = options.gap;
|
|
441
|
-
}
|
|
442
|
-
}
|
|
443
|
-
// Build positioned children
|
|
444
|
-
const rows = [];
|
|
445
|
-
// Group items by row
|
|
446
|
-
const itemsByRow = new Map();
|
|
447
|
-
for (const [node, position] of layout.cells) {
|
|
448
|
-
for (let r = position.row; r < position.row + position.rowSpan; r++) {
|
|
449
|
-
if (!itemsByRow.has(r)) {
|
|
450
|
-
itemsByRow.set(r, []);
|
|
451
|
-
}
|
|
452
|
-
// Only add to first row of span
|
|
453
|
-
if (r === position.row) {
|
|
454
|
-
itemsByRow.get(r).push({ node, position });
|
|
455
|
-
}
|
|
456
|
-
}
|
|
457
|
-
}
|
|
458
|
-
// Create rows
|
|
459
|
-
const rowIndices = [...itemsByRow.keys()].sort((a, b) => a - b);
|
|
460
|
-
for (let i = 0; i < rowIndices.length; i++) {
|
|
461
|
-
const rowIndex = rowIndices[i];
|
|
462
|
-
const rowItems = itemsByRow.get(rowIndex) || [];
|
|
463
|
-
const rowHeight = layout.rowSizes[rowIndex - 1] || 1;
|
|
464
|
-
// Sort items by column
|
|
465
|
-
rowItems.sort((a, b) => a.position.column - b.position.column);
|
|
466
|
-
// Create cells for this row
|
|
467
|
-
const cells = [];
|
|
468
|
-
let currentCol = 1;
|
|
469
|
-
for (const { node, position } of rowItems) {
|
|
470
|
-
const itemOptions = gridItemData.get(node) || {};
|
|
471
|
-
// Add spacer for gap before this cell
|
|
472
|
-
if (position.column > currentCol) {
|
|
473
|
-
const gapCols = position.column - currentCol;
|
|
474
|
-
let spacerWidth = 0;
|
|
475
|
-
for (let c = currentCol; c < position.column; c++) {
|
|
476
|
-
spacerWidth += layout.columnSizes[c - 1] || 0;
|
|
477
|
-
if (c > currentCol)
|
|
478
|
-
spacerWidth += columnGap;
|
|
479
|
-
}
|
|
480
|
-
if (spacerWidth > 0) {
|
|
481
|
-
cells.push(Box({ width: spacerWidth }));
|
|
482
|
-
}
|
|
483
|
-
}
|
|
484
|
-
// Calculate cell width
|
|
485
|
-
let cellWidth = 0;
|
|
486
|
-
for (let c = position.column; c < position.column + position.columnSpan; c++) {
|
|
487
|
-
cellWidth += layout.columnSizes[c - 1] || 0;
|
|
488
|
-
if (c > position.column)
|
|
489
|
-
cellWidth += columnGap;
|
|
490
|
-
}
|
|
491
|
-
// Calculate cell height
|
|
492
|
-
let cellHeight = 0;
|
|
493
|
-
for (let r = position.row; r < position.row + position.rowSpan; r++) {
|
|
494
|
-
cellHeight += layout.rowSizes[r - 1] || 0;
|
|
495
|
-
if (r > position.row)
|
|
496
|
-
cellHeight += rowGap;
|
|
497
|
-
}
|
|
498
|
-
// Apply alignment
|
|
499
|
-
const justifySelf = itemOptions.justifySelf ?? options.justifyItems ?? 'stretch';
|
|
500
|
-
const alignSelf = itemOptions.alignSelf ?? options.alignItems ?? 'stretch';
|
|
501
|
-
let justifyContent;
|
|
502
|
-
let alignItems;
|
|
503
|
-
switch (justifySelf) {
|
|
504
|
-
case 'start':
|
|
505
|
-
justifyContent = 'flex-start';
|
|
506
|
-
break;
|
|
507
|
-
case 'end':
|
|
508
|
-
justifyContent = 'flex-end';
|
|
509
|
-
break;
|
|
510
|
-
case 'center':
|
|
511
|
-
justifyContent = 'center';
|
|
512
|
-
break;
|
|
513
|
-
case 'stretch':
|
|
514
|
-
default:
|
|
515
|
-
justifyContent = 'flex-start';
|
|
516
|
-
break;
|
|
517
|
-
}
|
|
518
|
-
switch (alignSelf) {
|
|
519
|
-
case 'start':
|
|
520
|
-
alignItems = 'flex-start';
|
|
521
|
-
break;
|
|
522
|
-
case 'end':
|
|
523
|
-
alignItems = 'flex-end';
|
|
524
|
-
break;
|
|
525
|
-
case 'center':
|
|
526
|
-
alignItems = 'center';
|
|
527
|
-
break;
|
|
528
|
-
case 'stretch':
|
|
529
|
-
default:
|
|
530
|
-
alignItems = 'flex-start';
|
|
531
|
-
break;
|
|
532
|
-
}
|
|
533
|
-
cells.push(Box({
|
|
534
|
-
width: cellWidth,
|
|
535
|
-
height: cellHeight,
|
|
536
|
-
justifyContent,
|
|
537
|
-
alignItems,
|
|
538
|
-
}, node));
|
|
539
|
-
currentCol = position.column + position.columnSpan;
|
|
540
|
-
}
|
|
541
|
-
// Add row gap if not first row
|
|
542
|
-
if (i > 0 && rowGap > 0) {
|
|
543
|
-
rows.push(Box({ height: rowGap }));
|
|
544
|
-
}
|
|
545
|
-
rows.push(Box({
|
|
546
|
-
flexDirection: 'row',
|
|
547
|
-
height: rowHeight,
|
|
548
|
-
}, ...cells));
|
|
549
|
-
}
|
|
550
|
-
// Wrap in container
|
|
551
|
-
const containerStyle = {
|
|
552
|
-
flexDirection: 'column',
|
|
553
|
-
width: options.width,
|
|
554
|
-
height: options.height,
|
|
555
|
-
padding: options.padding,
|
|
556
|
-
};
|
|
557
|
-
if (options.border) {
|
|
558
|
-
containerStyle.borderStyle = options.borderStyle ?? 'single';
|
|
559
|
-
containerStyle.borderColor = options.borderColor;
|
|
560
|
-
}
|
|
561
|
-
return Box(containerStyle, ...rows);
|
|
562
|
-
}
|
|
563
|
-
/**
|
|
564
|
-
* Grid item wrapper
|
|
565
|
-
*/
|
|
566
|
-
export function GridItem(options, ...children) {
|
|
567
|
-
const node = Box({}, ...children.filter((c) => c !== null));
|
|
568
|
-
gridItemData.set(node, options);
|
|
569
|
-
return node;
|
|
570
|
-
}
|
|
571
|
-
// =============================================================================
|
|
572
|
-
// Convenience Components
|
|
573
|
-
// =============================================================================
|
|
574
|
-
/**
|
|
575
|
-
* Simple row grid (equal columns)
|
|
576
|
-
*/
|
|
577
|
-
export function GridRow(options, ...children) {
|
|
578
|
-
const validChildren = children.filter((c) => c !== null);
|
|
579
|
-
const columnCount = options.columnCount ?? validChildren.length;
|
|
580
|
-
const columns = Array(columnCount).fill('1fr').join(' ');
|
|
581
|
-
return Grid({ ...options, columns }, ...validChildren);
|
|
582
|
-
}
|
|
583
|
-
/**
|
|
584
|
-
* Simple column grid (equal rows)
|
|
585
|
-
*/
|
|
586
|
-
export function GridColumn(options, ...children) {
|
|
587
|
-
const validChildren = children.filter((c) => c !== null);
|
|
588
|
-
const rowCount = options.rowCount ?? validChildren.length;
|
|
589
|
-
const rows = Array(rowCount).fill('1fr').join(' ');
|
|
590
|
-
return Grid({ ...options, columns: '1fr', rows }, ...validChildren);
|
|
591
|
-
}
|
|
592
|
-
/**
|
|
593
|
-
* Auto-fitting grid (responsive columns)
|
|
594
|
-
*/
|
|
595
|
-
export function AutoGrid(options, ...children) {
|
|
596
|
-
const containerWidth = options.width ?? 80;
|
|
597
|
-
const gap = typeof options.gap === 'number' ? options.gap : options.gap?.[1] ?? 0;
|
|
598
|
-
const columnCount = Math.floor((containerWidth + gap) / (options.minColumnWidth + gap));
|
|
599
|
-
const columns = Array(Math.max(1, columnCount)).fill('1fr').join(' ');
|
|
600
|
-
return Grid({ ...options, columns }, ...children);
|
|
601
|
-
}
|
|
602
|
-
/**
|
|
603
|
-
* Dashboard-style grid with named areas
|
|
604
|
-
*/
|
|
605
|
-
export function DashboardGrid(options, areas) {
|
|
606
|
-
const { width = 80, height, gap = 0, headerHeight = 3, footerHeight = 1, sidebarWidth = 20, border, borderStyle, borderColor, } = options;
|
|
607
|
-
const hasHeader = areas.header !== undefined;
|
|
608
|
-
const hasSidebar = areas.sidebar !== undefined;
|
|
609
|
-
const hasFooter = areas.footer !== undefined;
|
|
610
|
-
// Build columns
|
|
611
|
-
const columns = hasSidebar ? `${sidebarWidth} 1fr` : '1fr';
|
|
612
|
-
// Build rows
|
|
613
|
-
const rowParts = [];
|
|
614
|
-
if (hasHeader)
|
|
615
|
-
rowParts.push(`${headerHeight}`);
|
|
616
|
-
rowParts.push('1fr');
|
|
617
|
-
if (hasFooter)
|
|
618
|
-
rowParts.push(`${footerHeight}`);
|
|
619
|
-
const rows = rowParts.join(' ');
|
|
620
|
-
// Build areas template
|
|
621
|
-
const areaRows = [];
|
|
622
|
-
if (hasHeader) {
|
|
623
|
-
areaRows.push(hasSidebar ? '"header header"' : '"header"');
|
|
624
|
-
}
|
|
625
|
-
areaRows.push(hasSidebar ? '"sidebar main"' : '"main"');
|
|
626
|
-
if (hasFooter) {
|
|
627
|
-
areaRows.push(hasSidebar ? '"footer footer"' : '"footer"');
|
|
628
|
-
}
|
|
629
|
-
const areasTemplate = areaRows.join('\n');
|
|
630
|
-
const children = [];
|
|
631
|
-
if (areas.header) {
|
|
632
|
-
children.push(GridItem({ area: 'header' }, areas.header));
|
|
633
|
-
}
|
|
634
|
-
if (areas.sidebar) {
|
|
635
|
-
children.push(GridItem({ area: 'sidebar' }, areas.sidebar));
|
|
636
|
-
}
|
|
637
|
-
children.push(GridItem({ area: 'main' }, areas.main));
|
|
638
|
-
if (areas.footer) {
|
|
639
|
-
children.push(GridItem({ area: 'footer' }, areas.footer));
|
|
640
|
-
}
|
|
641
|
-
return Grid({
|
|
642
|
-
width,
|
|
643
|
-
height,
|
|
644
|
-
columns,
|
|
645
|
-
rows,
|
|
646
|
-
areas: areasTemplate,
|
|
647
|
-
gap,
|
|
648
|
-
border,
|
|
649
|
-
borderStyle,
|
|
650
|
-
borderColor,
|
|
651
|
-
}, ...children);
|
|
652
|
-
}
|
|
653
|
-
/**
|
|
654
|
-
* Masonry-style grid (variable height items)
|
|
655
|
-
*/
|
|
656
|
-
export function MasonryGrid(options, ...children) {
|
|
657
|
-
const validChildren = children.filter((c) => c !== null);
|
|
658
|
-
const { columns: columnCount, gap = 0, width = 80 } = options;
|
|
659
|
-
// Track column heights
|
|
660
|
-
const columnHeights = new Array(columnCount).fill(0);
|
|
661
|
-
// Place items in shortest column
|
|
662
|
-
const placedItems = [];
|
|
663
|
-
for (const child of validChildren) {
|
|
664
|
-
// Find shortest column
|
|
665
|
-
let shortestCol = 0;
|
|
666
|
-
let shortestHeight = columnHeights[0];
|
|
667
|
-
for (let i = 1; i < columnCount; i++) {
|
|
668
|
-
if (columnHeights[i] < shortestHeight) {
|
|
669
|
-
shortestHeight = columnHeights[i];
|
|
670
|
-
shortestCol = i;
|
|
671
|
-
}
|
|
672
|
-
}
|
|
673
|
-
placedItems.push({ node: child, column: shortestCol });
|
|
674
|
-
columnHeights[shortestCol] += 1; // Assume height 1 for simplicity
|
|
675
|
-
}
|
|
676
|
-
// Build column containers
|
|
677
|
-
const columnNodes = [];
|
|
678
|
-
const columnWidth = Math.floor((width - (columnCount - 1) * gap) / columnCount);
|
|
679
|
-
for (let col = 0; col < columnCount; col++) {
|
|
680
|
-
const columnItems = placedItems.filter((item) => item.column === col).map((item) => item.node);
|
|
681
|
-
columnNodes.push(Box({
|
|
682
|
-
flexDirection: 'column',
|
|
683
|
-
width: columnWidth,
|
|
684
|
-
gap,
|
|
685
|
-
}, ...columnItems));
|
|
686
|
-
}
|
|
687
|
-
return Box({
|
|
688
|
-
flexDirection: 'row',
|
|
689
|
-
gap,
|
|
690
|
-
width,
|
|
691
|
-
}, ...columnNodes);
|
|
692
|
-
}
|
|
693
|
-
// =============================================================================
|
|
694
|
-
// Utility Functions
|
|
695
|
-
// =============================================================================
|
|
696
|
-
/**
|
|
697
|
-
* Create a repeat track definition
|
|
698
|
-
*/
|
|
699
|
-
export function repeat(count, track) {
|
|
700
|
-
if (typeof track === 'number') {
|
|
701
|
-
return Array(count).fill(`${track}`).join(' ');
|
|
702
|
-
}
|
|
703
|
-
return Array(count).fill(track).join(' ');
|
|
704
|
-
}
|
|
705
|
-
/**
|
|
706
|
-
* Create a minmax track
|
|
707
|
-
*/
|
|
708
|
-
export function minmax(min, max) {
|
|
709
|
-
const minStr = typeof min === 'number' ? `${min}` : min;
|
|
710
|
-
const maxStr = typeof max === 'number' ? `${max}` : max;
|
|
711
|
-
return `minmax(${minStr},${maxStr})`;
|
|
712
|
-
}
|
|
713
|
-
/**
|
|
714
|
-
* Calculate grid template from areas
|
|
715
|
-
*/
|
|
716
|
-
export function gridAreasToTemplate(areas) {
|
|
717
|
-
return areas.map((row) => `"${row.join(' ')}"`).join('\n');
|
|
718
|
-
}
|
|
719
|
-
//# sourceMappingURL=grid.js.map
|