diff --git a/examples/grid-lite/components-react/package.json b/examples/grid-lite/components-react/package.json index cd5b45a..b98f691 100644 --- a/examples/grid-lite/components-react/package.json +++ b/examples/grid-lite/components-react/package.json @@ -16,11 +16,12 @@ "react-dom": ">=18" }, "devDependencies": { + "@tailwindcss/vite": "^4.3.2", "@types/react": ">=18", "@types/react-dom": ">=18", "@vitejs/plugin-react": "^4.2.0", + "tailwindcss": "^4.3.2", "typescript": "^5.0.0", "vite": "^5.0.0" } } - diff --git a/examples/grid-lite/components-react/src/App.tsx b/examples/grid-lite/components-react/src/App.tsx index cdb84e1..eabd17b 100644 --- a/examples/grid-lite/components-react/src/App.tsx +++ b/examples/grid-lite/components-react/src/App.tsx @@ -71,102 +71,120 @@ function App() { // }; return ( - <> - - - - Grid Caption v2.1 -
- - - - - - Grid Description - - -
- - {/* */} +
+ + + + Grid styled by Tailwind CSS +
+ + + + + + Grid Description + + +
+ + {/* */} +
- ); } diff --git a/examples/grid-lite/components-react/src/index.css b/examples/grid-lite/components-react/src/index.css index 9a63579..c050702 100644 --- a/examples/grid-lite/components-react/src/index.css +++ b/examples/grid-lite/components-react/src/index.css @@ -1,8 +1,7 @@ -* { - margin: 0; - padding: 0; - box-sizing: border-box; -} +@import "tailwindcss"; + +/* Optional: load default Grid theme tokens + themed caption styles */ +/* @import "@highcharts/grid-lite-react/src/styles/grid-theme-default.css"; */ body { font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', @@ -15,19 +14,4 @@ body { #root { width: 100%; min-height: 100vh; - padding: 20px; -} - -#controls { - margin-top: 20px; - display: flex; - gap: 10px; -} - -@media (prefers-color-scheme: dark) { - body { - background-color: #121212; - color: #ffffff; - } -} - +} \ No newline at end of file diff --git a/examples/grid-lite/components-react/vite.config.ts b/examples/grid-lite/components-react/vite.config.ts index 2e3f28b..0ec7891 100644 --- a/examples/grid-lite/components-react/vite.config.ts +++ b/examples/grid-lite/components-react/vite.config.ts @@ -1,12 +1,13 @@ import { defineConfig } from 'vite'; import react from '@vitejs/plugin-react'; +import tailwindcss from '@tailwindcss/vite'; import { resolve, dirname } from 'path'; import { fileURLToPath } from 'url'; const __dirname = dirname(fileURLToPath(import.meta.url)); export default defineConfig({ - plugins: [react()], + plugins: [react(), tailwindcss()], resolve: { alias: [ { @@ -24,6 +25,7 @@ export default defineConfig({ ] }, server: { + host: true, port: 3000 } }); diff --git a/packages/grid-lite-react/src/Grid.tsx b/packages/grid-lite-react/src/Grid.tsx index aa47803..25e3a77 100644 --- a/packages/grid-lite-react/src/Grid.tsx +++ b/packages/grid-lite-react/src/Grid.tsx @@ -15,20 +15,28 @@ import { } from '@highcharts/grid-shared-react'; import { merge } from '@highcharts/grid-lite/es-modules/Shared/Utilities.js'; import Grid from '@highcharts/grid-lite/es-modules/masters/grid-lite.src'; -import '@highcharts/grid-lite/css/grid-lite.css'; +import './styles/grid-core.css'; import type { Options } from '@highcharts/grid-lite/es-modules/Grid/Core/Options'; export default function GridLite(props: GridProps) { - const { gridRef, children, options, ...gridProps } = props; + const { gridRef, children, options, theme, className, ...gridProps } = props; const childOptions = useMemo(() => getChildProps(children), [children]); const columnKey = useMemo(() => { const columns = childOptions.columns as Array<{ id?: string }> | undefined; return columns?.map((column) => column.id).join('\0') ?? ''; }, [childOptions]); + const containerTheme = useMemo( + () => [theme, className].filter(Boolean).join(' ') || void 0, + [theme, className] + ); const gridOptions = useMemo( - () => merge(childOptions, options ?? {}) as Options, - [childOptions, options] + () => merge( + childOptions, + options ?? {}, + containerTheme ? { rendering: { theme: containerTheme } } : {} + ) as Options, + [childOptions, options, containerTheme] ); return ( diff --git a/packages/grid-lite-react/src/styles/grid-core.css b/packages/grid-lite-react/src/styles/grid-core.css new file mode 100644 index 0000000..ccd0493 --- /dev/null +++ b/packages/grid-lite-react/src/styles/grid-core.css @@ -0,0 +1,680 @@ +@import '@highcharts/grid-lite/css/modules/grid-base-variables.css'; +@import '@highcharts/grid-lite/css/modules/grid-popup-variables.css'; +@import '@highcharts/grid-lite/css/modules/grid-menu-variables.css'; +@import '@highcharts/grid-lite/css/modules/grid-link-variables.css'; +@import '@highcharts/grid-lite/css/modules/grid-input-variables.css'; +@import '@highcharts/grid-lite/css/modules/grid-button-variables.css'; +@import '@highcharts/grid-lite/css/modules/grid-icon-variables.css'; +@import '@highcharts/grid-lite/css/modules/grid-pagination-variables.css'; +@import '@highcharts/grid-lite/css/modules/grid-table-variables.css'; +/* Grid container */ +.hcg-container { + container-type: inline-size; + container-name: hcg; + position: relative; + display: flex; + flex-direction: column; + height: 100%; + overflow: hidden; + box-sizing: border-box; + color-scheme: light dark; + max-height: inherit; +} + +.highcharts-light .hcg-container { + color-scheme: light; +} + +.highcharts-dark .hcg-container { + color-scheme: dark; +} + +.hcg-container * { + box-sizing: border-box; +} + +.hcg-container:has(.hcg-no-data) { + justify-content: center; + align-items: center; +} + +/* ---------------------------------------------------------- + INPUT ELEMENTS +------------------------------------------------------------ */ + +.hcg-container .hcg-input { + width: 100%; + + &:disabled { + opacity: 0.4; + cursor: not-allowed; + } + + &::placeholder { + color: #767676; + } + + &:focus-visible { + outline: none; + border-color: transparent; + } + + &[type="checkbox"] { + --ig-input-checkbox-size: 1.333em; + + appearance: none; + width: var(--ig-input-checkbox-size); + height: var(--ig-input-checkbox-size); + cursor: pointer; + position: relative; + + &:checked::before { + content: ""; + position: absolute; + inset: 0; + margin: 0.05em; + mask: center/contain no-repeat; + mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='3' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M5 13l4 4L19 7'/%3E%3C/svg%3E"); + } + } + + &.hcg-icon-search { + padding-left: 25px; + appearance: none; + background-repeat: no-repeat; + background-position: left 10px center; + background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 12 12' fill='none'%3e%3cpath d='M10.5 10.5L7.50005 7.5M8.5 5C8.5 6.933 6.933 8.5 5 8.5C3.067 8.5 1.5 6.933 1.5 5C1.5 3.067 3.067 1.5 5 1.5C6.933 1.5 8.5 3.067 8.5 5Z' stroke='%23767676' stroke-linecap='round' stroke-linejoin='round'/%3e%3c/svg%3e"); + } + + select& { + appearance: none; + background-image: url("data:image/svg+xml,%3csvg width='12' height='12' viewBox='0 0 12 12' fill='none' xmlns='http://www.w3.org/2000/svg'%3e%3cpath d='M3.5 7.5L6 10L8.5 7.5M3.5 4.5L6 2L8.5 4.5' stroke='%23767676' stroke-linecap='round' stroke-linejoin='round'/%3e%3c/svg%3e"); + background-repeat: no-repeat; + background-position: right 5px center; + white-space: nowrap; + text-overflow: ellipsis; + } +} + +/* ---------------------------------------------------------- + BUTTON ELEMENT +------------------------------------------------------------ */ + +.hcg-container :is(.hcg-button, .hcg-icon) { + position: relative; + display: inline-flex; + vertical-align: middle; + align-items: center; + justify-content: center; + flex-direction: row; + line-height: 1; + gap: 2px; + cursor: pointer; + transition: background-color 0.2s ease, box-shadow 0.2s ease, border 0.2s ease; + + svg { + width: 0.9em; + height: 0.9em; + display: block; + } + + span { + display: inline-block; + line-height: 1; + } + + span:empty { + display: none; + } + + &.reverse { + flex-direction: row-reverse; + } + + &:focus-visible { + outline: none; + border-color: transparent; + } + + &:disabled { + opacity: 0.4; + cursor: not-allowed; + } +} + +/* ---------------------------------------------------------- + TABLE ELEMENTS +------------------------------------------------------------ */ + +/* */ +.hcg-container .hcg-table { + width: 100%; + border-collapse: separate; + border-spacing: 0; + overflow: hidden; + table-layout: fixed; + flex: 1; + + &.hcg-scrollable-content { + display: flex; + flex-direction: column; + min-height: 0; + } + + /* */ + &.hcg-virtualization thead { + display: block; + } + + thead th { + position: relative; + } + + /* */ + &.hcg-scrollable-content > tbody { + height: 100%; + overflow: auto; + min-height: 0; + flex: 1; + } + + &.hcg-virtualization > tbody { + display: block; + position: relative; + } + + > tbody > tr { + overflow: hidden; + width: 100%; + } + + > tbody > tr > :where(.hcg-cell) { + position: relative; + line-height: 1em; + overflow: hidden; + } + + > tbody > tr.hcg-mocked-row > :where(.hcg-cell) { + white-space: nowrap; + text-overflow: ellipsis; + } + + .hcg-last-header-cell-in-row, + tbody tr > :where(.hcg-cell):last-child { + border-right: none; + } + + tbody tr:last-of-type > :where(.hcg-cell) { + border-bottom: none; + } + + &.hcg-scrollable-content > tbody > tr { + display: block; + } + + &.hcg-virtualization > tbody > tr { + position: absolute; + } + + > tbody.hcg-rows-content-nowrap > tr > :where(.hcg-cell) { + white-space: nowrap; + text-overflow: ellipsis; + } + + > tbody > tr > :where(.hcg-cell):focus { + outline: none; + } +} + +/* ---------------------------------------------------------- + HEADER ELEMENTS +------------------------------------------------------------ */ +.hcg-container thead th { + .hcg-header-cell-container { + display: flex; + align-items: center; + justify-content: space-between; + } + + .hcg-header-cell-content { + flex: 1; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + } + + .hcg-header-cell-container.hcg-no-width .hcg-header-cell-content { + visibility: hidden; + transition: none; + } + + .hcg-header-cell-icons { + display: flex; + overflow: hidden; + align-items: center; + max-width: 0; + opacity: 0; + cursor: pointer; + transition: max-width 0.3s ease, opacity 0.3s ease; + } + + .hcg-header-cell-icons .hcg-icon.hcg-icon-selected::after { + content: ""; + position: absolute; + top: 2px; + right: 2px; + width: 0.3em; + height: 0.3em; + border-radius: 50%; + background: currentColor; + } + + :is(:hover, :focus-visible) .hcg-header-cell-icons, + .hcg-header-cell-icons:has(.hcg-button:focus-visible, .hcg-icon:focus-visible, .hcg-button.hcg-button-selected, .hcg-icon.hcg-icon-highlighted, .hcg-icon.hcg-icon-selected), + .hcg-header-cell-container.hcg-no-width .hcg-header-cell-icons { + max-width: 100px; + opacity: 1; + } + + .hcg-header-cell-container.hcg-no-width .hcg-header-cell-menu-icon { + position: absolute; + left: 50%; + top: 50%; + transform: translate(-50%, -50%); + margin-left: 0; + } + + .hcg-header-cell-icons .hcg-header-cell-menu-icon .hcg-icon { + padding-inline: 3px; + } + + .hcg-header-cell-icons > :first-child { + margin-left: 5px; + } + + .hcg-column-resizer { + position: absolute; + display: flex; + align-items: center; + justify-content: center; + top: 0; + width: 9px; + right: -5px; + height: 100%; + user-select: none; + touch-action: none; + z-index: 10; + cursor: col-resize; + } + + .hcg-column-resizer.hovered::after { + content: ""; + height: 100%; + } +} + +/* ---------------------------------------------------------- + PAGINATION ELEMENTS +------------------------------------------------------------ */ + +.hcg-container .hcg-pagination { + display: flex; + align-items: center; + gap: 0.75rem; + flex-wrap: nowrap; + + > * { + flex: 1 1 0; + min-width: 0; + display: flex; + align-items: center; + } + + .hcg-pagination-info { + justify-content: flex-start; + } + + .hcg-pagination-controls { + justify-content: center; + gap: 2px; + + .hcg-pagination-pages { + display: flex; + flex-wrap: nowrap; + gap: 2px; + + .hcg-button { + display: inline-flex; + align-items: center; + justify-content: center; + min-width: 30px; + } + + span { + display: inline-flex; + align-items: center; + justify-content: center; + min-width: 20px; + } + } + } + + .hcg-pagination-page-size { + justify-content: flex-end; + text-align: right; + + select.hcg-input { + width: 60px; + margin-left: 8px; + } + } + + /* .hcg-pagination-nav-dropdown { + display: none; + min-width: 200px; + } */ + + &.hcg-pagination-left, + &.hcg-pagination-center, + &.hcg-pagination-right { + > * { + flex: 0 0 auto; + min-width: auto; + } + } + + &.hcg-pagination-left { justify-content: flex-start; } + &.hcg-pagination-center { justify-content: center; } + &.hcg-pagination-right { justify-content: flex-end; } + + &:not(:has(.hcg-pagination-info)) .hcg-pagination-controls { + justify-content: flex-start; + } + + &:not(:has(.hcg-pagination-page-size)) .hcg-pagination-controls { + justify-content: flex-end; + } +} + +@container hcg (max-width: 800px) { + .hcg-container .hcg-pagination { + flex-direction: column; + align-items: stretch; + --ig-pagination-stacked-align: center; + + &.hcg-pagination-left { --ig-pagination-stacked-align: flex-start; } + &.hcg-pagination-right { --ig-pagination-stacked-align: flex-end; } + + > * { + flex: 0 0 auto; + justify-content: var(--ig-pagination-stacked-align); + } + + .hcg-pagination-info, + .hcg-pagination-controls, + .hcg-pagination-page-size { + justify-content: var(--ig-pagination-stacked-align); + } + + .hcg-pagination-page-size { + text-align: center; + } + &.hcg-pagination-left .hcg-pagination-page-size { text-align: left; } + &.hcg-pagination-right .hcg-pagination-page-size { text-align: right; } + + &:not(:has(.hcg-pagination-page-size)) .hcg-pagination-controls, + &:not(:has(.hcg-pagination-info)) .hcg-pagination-controls { + justify-content: var(--ig-pagination-stacked-align); + } + } +} + +/* ---------------------------------------------------------- + CREDITS ELEMENT +------------------------------------------------------------ */ + +.hcg-credits, +.highcharts-light .hcg-credits { + display: block; + width: 114px; + height: 20px; + background-size: contain; + background-repeat: no-repeat; + background-image: + image-set( + /* stylelint-disable-next-line function-comma-newline-after */ + url("https://assets.highcharts.com/grid/logo_light.png") 1x, + url("https://assets.highcharts.com/grid/logo_lightx2.png") 2x + ); +} + +@media (prefers-color-scheme: dark) { + .hcg-credits { + background-image: + image-set( + /* stylelint-disable-next-line function-comma-newline-after */ + url("https://assets.highcharts.com/grid/logo_dark.png") 1x, + url("https://assets.highcharts.com/grid/logo_darkx2.png") 2x + ); + } +} + +.highcharts-dark .hcg-credits { + background-image: + image-set( + /* stylelint-disable-next-line function-comma-newline-after */ + url("https://assets.highcharts.com/grid/logo_dark.png") 1x, + url("https://assets.highcharts.com/grid/logo_darkx2.png") 2x + ); +} + +/* ---------------------------------------------------------- + POPUP ELEMENTS +------------------------------------------------------------ */ +.hcg-container .hcg-popup { + position: absolute; + z-index: 1000; + border-radius: 6px; + box-shadow: 0 2px 4px 0 rgba(0, 0, 0, 0.08), 0 7px 7px 0 rgba(0, 0, 0, 0.07), 0 17px 10px 0 rgba(0, 0, 0, 0.04), 0 30px 12px 0 rgba(0, 0, 0, 0.01); + min-width: 200px; + overflow: auto; + border-width: 1px; + border-style: solid; + + .hcg-popup-content { + padding: 5px; + } + + .hcg-menu-header { + font-size: 0.75rem; + padding: 3px; + margin-bottom: 5px; + } + + .hcg-menu-header-category { + opacity: 0.5; + user-select: none; + } +} + +/* ---------------------------------------------------------- + MENU ELEMENTS +------------------------------------------------------------ */ + +.hcg-container .hcg-menu-container { + margin: 0; + display: flex; + flex-direction: column; + list-style: none; + row-gap: 5px; + padding: 0; + + .hcg-menu-item { + display: flex; + align-items: center; + gap: 2px; + width: 100%; + min-width: 185px; + min-height: 2rem; + padding: 8px 8px 8px 12px; + font-size: 0.75rem; + font-weight: 600; + background-color: transparent; + border: 1px solid transparent; + border-radius: 5px; + } + + .hcg-menu-item:not(:disabled) { + cursor: pointer; + } + + .hcg-menu-item:focus-visible { + outline: none; + } + + .hcg-menu-item-icon { + --icon-size: 16px; + + flex: 0 0 var(--icon-size); + width: var(--icon-size); + height: var(--icon-size); + display: inline-flex; + align-items: center; + justify-content: center; + opacity: 0.6; + } + + .hcg-menu-item.active .hcg-menu-item-icon, + .hcg-menu-item.highlighted .hcg-menu-item-icon, + .hcg-menu-item:not(:disabled):hover .hcg-menu-item-icon { + opacity: 1; + } + + .hcg-menu-item-label { + flex: 1 1 auto; + min-width: 0; + text-align: left; + padding-left: 0.75rem; + } + + .hcg-menu-divider { + border-top-width: 1px; + border-top-style: solid; + height: 0; + } +} + +/* ---------------------------------------------------------- + FILTERING ELEMENTS +------------------------------------------------------------ */ + +.hcg-header-cell:has(.hcg-column-filter-wrapper) { + overflow: hidden; +} + +.hcg-column-filter-wrapper { + width: 100%; + display: flex; + flex-flow: column; + row-gap: 5px; + min-width: 50px; +} + +.hcg-clear-filter-button { + appearance: none; + background: none; + border: 0; + padding: 0; + margin: 0; + display: inline; + vertical-align: baseline; + font: inherit; + font-size: 0.625rem; + white-space: nowrap; + font-weight: normal; + align-self: end; +} + +.hcg-clear-filter-button:hover { + text-decoration: underline; + cursor: pointer; +} + +.hcg-clear-filter-button:disabled, +.hcg-clear-filter-button:disabled:hover { + opacity: 0.5; + text-decoration: none; + cursor: default; +} + +/* ---------------------------------------------------------- + OTHER ELEMENTS +------------------------------------------------------------ */ + +/* Sorting */ +.hcg-table thead th.hcg-column-sortable { + cursor: pointer; +} + +/* Accessibility */ +.hcg-visually-hidden { + position: absolute; + width: 1px; + height: 1px; + overflow: hidden; + white-space: nowrap; + clip: rect(1px, 1px, 1px, 1px); + margin-top: -3px; + opacity: 0.01; +} + +/* Loader */ +.hcg-loading-wrapper { + display: flex; + align-items: center; + justify-content: center; + position: absolute; + width: 100%; + height: 100%; + gap: 10px; + color: light-dark(#000000, #ffffff); +} + +.hcg-loading-wrapper .hcg-spinner { + border-top-width: 5px; + border-top-style: solid; + border-top-color: light-dark(#000000, #ffffff); + border-radius: 50%; + width: 30px; + height: 30px; + animation: spin 1s linear infinite; +} + +@keyframes spin { + from { + transform: rotate(0deg); + } + + to { + transform: rotate(360deg); + } +} + +/* Start Grid CSS Helpers Classes */ + +.hcg-table thead tr th.hcg-right .hcg-header-cell-content, +.hcg-table tbody tr > :where(.hcg-cell).hcg-right { + text-align: right; +} + +.hcg-table thead tr th.hcg-center .hcg-header-cell-content, +.hcg-table tbody tr > :where(.hcg-cell).hcg-center { + text-align: center; +} + +.hcg-table thead tr th.hcg-left .hcg-header-cell-content, +.hcg-table tbody tr > :where(.hcg-cell).hcg-left { + text-align: left; +} + +/* End Grid CSS Helpers Classes */ diff --git a/packages/grid-lite-react/src/styles/grid-theme-default.css b/packages/grid-lite-react/src/styles/grid-theme-default.css new file mode 100644 index 0000000..7e85955 --- /dev/null +++ b/packages/grid-lite-react/src/styles/grid-theme-default.css @@ -0,0 +1,63 @@ +@import '@highcharts/grid-lite/css/modules/grid-theme-default.css'; + +.hcg-theme-default { + --hcg-description-color: var(--hcg-color); + --hcg-description-background: transparent; + --hcg-description-font-weight: normal; + --hcg-description-font-size: var(--hcg-font-size); + --hcg-description-font-family: inherit; + --hcg-description-line-height: normal; + --hcg-description-letter-spacing: normal; + --hcg-description-text-align: left; + --hcg-description-margin-top: 0; + --hcg-description-margin-right: 0; + --hcg-description-margin-bottom: 0; + --hcg-description-margin-left: 0; + --hcg-description-padding-top: var(--hcg-padding); + --hcg-description-padding-right: var(--hcg-padding); + --hcg-description-padding-bottom: 0; + --hcg-description-padding-left: var(--hcg-padding); +} + +.hcg-theme-default .hcg-caption { + color: var(--hcg-caption-color); + background: var(--hcg-caption-background); + font-weight: var(--hcg-caption-font-weight); + font-size: var(--hcg-caption-font-size); + font-family: var(--hcg-caption-font-family); + line-height: var(--hcg-caption-line-height); + letter-spacing: var(--hcg-caption-letter-spacing); + text-align: var(--hcg-caption-text-align); + margin-top: var(--hcg-caption-margin-top); + margin-right: var(--hcg-caption-margin-right); + margin-bottom: var(--hcg-caption-margin-bottom); + margin-left: var(--hcg-caption-margin-left); + padding-top: var(--hcg-caption-padding-top); + padding-right: var(--hcg-caption-padding-right); + padding-bottom: var(--hcg-caption-padding-bottom); + padding-left: var(--hcg-caption-padding-left); +} + +.hcg-theme-default.hcg-caption * { + font: inherit; + margin: var(--hcg-caption-child-margin); +} + +.hcg-theme-default .hcg-description { + color: var(--hcg-description-color); + background: var(--hcg-description-background); + font-weight: var(--hcg-description-font-weight); + font-size: var(--hcg-description-font-size); + font-family: var(--hcg-description-font-family); + line-height: var(--hcg-description-line-height); + letter-spacing: var(--hcg-description-letter-spacing); + text-align: var(--hcg-description-text-align); + margin-top: var(--hcg-description-margin-top); + margin-right: var(--hcg-description-margin-right); + margin-bottom: var(--hcg-description-margin-bottom); + margin-left: var(--hcg-description-margin-left); + padding-top: var(--hcg-description-padding-top); + padding-right: var(--hcg-description-padding-right); + padding-bottom: var(--hcg-description-padding-bottom); + padding-left: var(--hcg-description-padding-left); +} diff --git a/packages/grid-pro-react/src/Grid.tsx b/packages/grid-pro-react/src/Grid.tsx index c236cfd..a70800b 100644 --- a/packages/grid-pro-react/src/Grid.tsx +++ b/packages/grid-pro-react/src/Grid.tsx @@ -19,16 +19,24 @@ import '@highcharts/grid-pro/css/grid-pro.css'; import type { Options } from '@highcharts/grid-pro/es-modules/Grid/Core/Options'; export default function GridPro(props: GridProps) { - const { gridRef, children, options, ...gridProps } = props; + const { gridRef, children, options, theme, className, ...gridProps } = props; const childOptions = useMemo(() => getChildProps(children), [children]); const columnKey = useMemo(() => { const columns = childOptions.columns as Array<{ id?: string }> | undefined; return columns?.map((column) => column.id).join('\0') ?? ''; }, [childOptions]); + const containerTheme = useMemo( + () => [theme, className].filter(Boolean).join(' ') || void 0, + [theme, className] + ); const gridOptions = useMemo( - () => merge(childOptions, options ?? {}) as Options, - [childOptions, options] + () => merge( + childOptions, + options ?? {}, + containerTheme ? { rendering: { theme: containerTheme } } : {} + ) as Options, + [childOptions, options, containerTheme] ); return ( diff --git a/packages/grid-shared-react/src/components/BaseGrid.tsx b/packages/grid-shared-react/src/components/BaseGrid.tsx index 4d51c20..917eb36 100644 --- a/packages/grid-shared-react/src/components/BaseGrid.tsx +++ b/packages/grid-shared-react/src/components/BaseGrid.tsx @@ -32,6 +32,15 @@ export interface GridProps { * Grid configuration options */ options?: TOptions; + /** + * Optional CSS class names applied on the Grid container (`hcg-container`), + * merged with `theme` into `rendering.theme`. + */ + className?: string; + /** + * Optional theme name passed to Grid Core. + */ + theme?: string; /** * Declarative option components (e.g. Caption) passed as children. */ @@ -53,13 +62,14 @@ export interface BaseGridProps { options?: TOptions; Grid: GridType; callback?: (grid: GridInstance) => void; + className?: string; } export const BaseGrid = forwardRef(function BaseGrid( props: BaseGridProps, ref: ForwardedRef> ) { - const { options, Grid, callback } = props; + const { options, Grid, callback, className } = props; const containerRef = useRef(null); const currGridRef = useGrid({ @@ -79,5 +89,5 @@ export const BaseGrid = forwardRef(function BaseGrid( [] ); - return
; + return
; }); diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index ff81d18..e4aa239 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -13,7 +13,7 @@ importers: version: 9.39.1 '@stylistic/eslint-plugin': specifier: ^5.6.1 - version: 5.6.1(eslint@9.39.1) + version: 5.6.1(eslint@9.39.1(jiti@2.7.0)) '@testing-library/react': specifier: ^16.3.1 version: 16.3.1(@testing-library/dom@10.4.1)(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(react-dom@19.2.1(react@19.2.1))(react@19.2.1) @@ -22,13 +22,13 @@ importers: version: 20.19.26 '@vitest/browser': specifier: ^4.0.16 - version: 4.0.16(vite@7.2.7(@types/node@20.19.26))(vitest@4.0.16) + version: 4.0.16(vite@7.2.7(@types/node@20.19.26)(jiti@2.7.0)(lightningcss@1.32.0))(vitest@4.0.16) '@vitest/browser-playwright': specifier: ^4.0.16 - version: 4.0.16(playwright@1.57.0)(vite@7.2.7(@types/node@20.19.26))(vitest@4.0.16) + version: 4.0.16(playwright@1.57.0)(vite@7.2.7(@types/node@20.19.26)(jiti@2.7.0)(lightningcss@1.32.0))(vitest@4.0.16) eslint: specifier: ^9.39.1 - version: 9.39.1 + version: 9.39.1(jiti@2.7.0) globals: specifier: ^17.0.0 version: 17.0.0 @@ -43,10 +43,10 @@ importers: version: 5.9.3 typescript-eslint: specifier: ^8.48.0 - version: 8.49.0(eslint@9.39.1)(typescript@5.9.3) + version: 8.49.0(eslint@9.39.1(jiti@2.7.0))(typescript@5.9.3) vitest: specifier: ^4.0.16 - version: 4.0.16(@types/node@20.19.26)(@vitest/browser-playwright@4.0.16)(jsdom@27.4.0) + version: 4.0.16(@types/node@20.19.26)(@vitest/browser-playwright@4.0.16)(jiti@2.7.0)(jsdom@27.4.0)(lightningcss@1.32.0) examples/grid-lite/components-react: dependencies: @@ -63,6 +63,9 @@ importers: specifier: '>=18' version: 19.2.1(react@19.2.1) devDependencies: + '@tailwindcss/vite': + specifier: ^4.3.2 + version: 4.3.2(vite@5.4.21(@types/node@20.19.26)(lightningcss@1.32.0)) '@types/react': specifier: '>=18' version: 19.2.7 @@ -71,13 +74,16 @@ importers: version: 19.2.3(@types/react@19.2.7) '@vitejs/plugin-react': specifier: ^4.2.0 - version: 4.7.0(vite@5.4.21(@types/node@20.19.26)) + version: 4.7.0(vite@5.4.21(@types/node@20.19.26)(lightningcss@1.32.0)) + tailwindcss: + specifier: ^4.3.2 + version: 4.3.2 typescript: specifier: ^5.0.0 version: 5.9.3 vite: specifier: ^5.0.0 - version: 5.4.21(@types/node@20.19.26) + version: 5.4.21(@types/node@20.19.26)(lightningcss@1.32.0) examples/grid-lite/minimal-nextjs: dependencies: @@ -133,13 +139,13 @@ importers: version: 19.2.3(@types/react@19.2.7) '@vitejs/plugin-react': specifier: ^4.2.0 - version: 4.7.0(vite@5.4.21(@types/node@20.19.26)) + version: 4.7.0(vite@5.4.21(@types/node@20.19.26)(lightningcss@1.32.0)) typescript: specifier: ^5.0.0 version: 5.9.3 vite: specifier: ^5.0.0 - version: 5.4.21(@types/node@20.19.26) + version: 5.4.21(@types/node@20.19.26)(lightningcss@1.32.0) examples/grid-pro/minimal-nextjs: dependencies: @@ -195,13 +201,13 @@ importers: version: 19.2.3(@types/react@19.2.7) '@vitejs/plugin-react': specifier: ^4.2.0 - version: 4.7.0(vite@5.4.21(@types/node@20.19.26)) + version: 4.7.0(vite@5.4.21(@types/node@20.19.26)(lightningcss@1.32.0)) typescript: specifier: ^5.0.0 version: 5.9.3 vite: specifier: ^5.0.0 - version: 5.4.21(@types/node@20.19.26) + version: 5.4.21(@types/node@20.19.26)(lightningcss@1.32.0) packages/grid-lite-react: dependencies: @@ -1055,6 +1061,96 @@ packages: '@swc/helpers@0.5.5': resolution: {integrity: sha512-KGYxvIOXcceOAbEk4bi/dVLEK9z8sZ0uBB3Il5b1rhfClSpcX0yfRO0KmTkqR2cnQDymwLB+25ZyMzICg/cm/A==} + '@tailwindcss/node@4.3.2': + resolution: {integrity: sha512-yWP/sqEcBLaD8JuA6zNwxoYKr75qxTioYwlRwekj5Jr/I5GXnoJfjetH/psLUIv74cYTH2lBUEzBkinthoYcBg==} + + '@tailwindcss/oxide-android-arm64@4.3.2': + resolution: {integrity: sha512-WHxqIuHpvZ5VtdX6GTl1Ik/Vp2YuN42Et+0CdeaVd/frQ9jAvGmvR8vLT+jk3e8/Q3x8kECB9+R17pgpp2BulA==} + engines: {node: '>= 20'} + cpu: [arm64] + os: [android] + + '@tailwindcss/oxide-darwin-arm64@4.3.2': + resolution: {integrity: sha512-GZypeUY/IDJW3877KeM+O67vbXr3MBnbtEL4aYhNErv/JWZhye2vGSWWG9tB6iiqR2MqRNkY8IOUy4NdSZV26w==} + engines: {node: '>= 20'} + cpu: [arm64] + os: [darwin] + + '@tailwindcss/oxide-darwin-x64@4.3.2': + resolution: {integrity: sha512-UIIzmefR6KO1sDU7MzRqAxC8iBpft/VhkGjTjnhoS6k7Z3rQ9wEgA1ODSiyH/tcSYssulNm4Ci3hOeK1jH7ccQ==} + engines: {node: '>= 20'} + cpu: [x64] + os: [darwin] + + '@tailwindcss/oxide-freebsd-x64@4.3.2': + resolution: {integrity: sha512-GN+uAmcI6DNspnCDwtOAZrTz6oukJnp337qZvxqCGLd3BHBzJpO0ZbTLRvJNdztOeAmTzewewGIMPb0tk2R4WA==} + engines: {node: '>= 20'} + cpu: [x64] + os: [freebsd] + + '@tailwindcss/oxide-linux-arm-gnueabihf@4.3.2': + resolution: {integrity: sha512-4ABn7qSbdHRwTiDiuWNegCyb5+2FJ4vKIKc3DmKrvAFw7MU1Lm11dIkTPwUaFdTzc7IsOpDbqBrlh0x6y36U/w==} + engines: {node: '>= 20'} + cpu: [arm] + os: [linux] + + '@tailwindcss/oxide-linux-arm64-gnu@4.3.2': + resolution: {integrity: sha512-wDgEIGwoM8w8pufh9LVt1PahDgNdKXrLC2qfAnV3vAmococ9RWbxeAw4pxPttd/TsJfwjyLf90Dg1y9y8I6Emw==} + engines: {node: '>= 20'} + cpu: [arm64] + os: [linux] + + '@tailwindcss/oxide-linux-arm64-musl@4.3.2': + resolution: {integrity: sha512-J5Nuk0uZQIiMTJj3LEx4sAA9tMFUoXQZFv1J6An+QGYe53HKRJuFDi0rpq/tuouCZeAbOBY3kQ6g8qeD4TUjtA==} + engines: {node: '>= 20'} + cpu: [arm64] + os: [linux] + + '@tailwindcss/oxide-linux-x64-gnu@4.3.2': + resolution: {integrity: sha512-kqCZpSKOBEJO4mz7OqWoofBZeXTAwaVGPj0ErAj7CojmhKpWVWVOnrt9dE8odoIraZq4oj3ausM37kXi+Tow8w==} + engines: {node: '>= 20'} + cpu: [x64] + os: [linux] + + '@tailwindcss/oxide-linux-x64-musl@4.3.2': + resolution: {integrity: sha512-cixpqbh2toJDmkuCRI68nXA8ZxNmdK9Y+9v5h3MC3ZQKy/0BO8AWzlkWyRM7JAFSGBlfig4YVTPsK6MVgqz1uw==} + engines: {node: '>= 20'} + cpu: [x64] + os: [linux] + + '@tailwindcss/oxide-wasm32-wasi@4.3.2': + resolution: {integrity: sha512-4ec2Z/LOmRsAgU23CS4xeJfcJlmRg94A/XrbGRCF1gyU/zdDfRLYDVsS+ynSZCmGNxQ1jQriQOKMQeQxBA3Isw==} + engines: {node: '>=14.0.0'} + cpu: [wasm32] + bundledDependencies: + - '@napi-rs/wasm-runtime' + - '@emnapi/core' + - '@emnapi/runtime' + - '@tybys/wasm-util' + - '@emnapi/wasi-threads' + - tslib + + '@tailwindcss/oxide-win32-arm64-msvc@4.3.2': + resolution: {integrity: sha512-Zyr/M0+XcYZu3bZrUytc7TXvrk0ftWfl8gN2MwekNDzhqhKRUucMPSeOzM0o0wH5AWOU49BsKRrfKxI2atCPMQ==} + engines: {node: '>= 20'} + cpu: [arm64] + os: [win32] + + '@tailwindcss/oxide-win32-x64-msvc@4.3.2': + resolution: {integrity: sha512-QI9BO7KlNZsp2GuO0jwAAj5jCDABOKXRkCk2XuKTSaNEFSdfzqswYVTtCHBNKHLsqyjFyFkqlDiwkNbTYSssMQ==} + engines: {node: '>= 20'} + cpu: [x64] + os: [win32] + + '@tailwindcss/oxide@4.3.2': + resolution: {integrity: sha512-z8ZgnzX8gdNoWLBLqBPoh/sjnxkwvf9ZuWjnO0l0yIzbLa5/9S+eC5QxGZKRobVHIC3/1BoMWjHblqWjcgFgag==} + engines: {node: '>= 20'} + + '@tailwindcss/vite@4.3.2': + resolution: {integrity: sha512-eHpMeX4JXfVNJDEcsouTeCBubJBTcTLigeaw/NTUW6PB5ATKKXdyonnXgTBX2VuRbjz1hjfz6C5XAhr52ImQXA==} + peerDependencies: + vite: ^5.2.0 || ^6 || ^7 || ^8 + '@testing-library/dom@10.4.1': resolution: {integrity: sha512-o4PXJQidqJl82ckFaXUeoAW+XysPLauYI43Abki5hABd853iMhitooc6znOnczgbTYmEP6U6/y1ZyKAIsvMKGg==} engines: {node: '>=18'} @@ -1360,12 +1456,20 @@ packages: resolution: {integrity: sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==} engines: {node: '>=6'} + detect-libc@2.1.2: + resolution: {integrity: sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==} + engines: {node: '>=8'} + dom-accessibility-api@0.5.16: resolution: {integrity: sha512-X7BJ2yElsnOJ30pZF4uIIDfBEVgF4XEBxL9Bxhy6dnrm5hkzqmsWHGTiHqRiITNhMyFLyAiWndIJP7Z1NTteDg==} electron-to-chromium@1.5.267: resolution: {integrity: sha512-0Drusm6MVRXSOJpGbaSVgcQsuB4hEkMpHXaVstcPmhu5LIedxs1xNK/nIxmQIU/RPC0+1/o0AVZfBTkTNJOdUw==} + enhanced-resolve@5.21.6: + resolution: {integrity: sha512-aNnGCvbJ/RIyWo1IuhNdVjnNF+EjH9wpzpNHt+ci/m9He9LJvUN8wrCcXjp9cWsGNAuvSpVFTx/vraAFQ8qGjQ==} + engines: {node: '>=10.13.0'} + entities@6.0.1: resolution: {integrity: sha512-aN97NXWF6AWBTahfVOIrB/NShkzi5H7F9r1s9mD3cDj4Ko5f2qhhVoYMibXF7GlLveb/D2ioWay8lxI97Ven3g==} engines: {node: '>=0.12'} @@ -1572,6 +1676,10 @@ packages: isexe@2.0.0: resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} + jiti@2.7.0: + resolution: {integrity: sha512-AC/7JofJvZGrrneWNaEnJeOLUx+JlGt7tNa0wZiRPT4MY1wmfKjt2+6O2p2uz2+skll8OZZmJMNqeke7kKbNgQ==} + hasBin: true + js-tokens@4.0.0: resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==} @@ -1614,6 +1722,76 @@ packages: resolution: {integrity: sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==} engines: {node: '>= 0.8.0'} + lightningcss-android-arm64@1.32.0: + resolution: {integrity: sha512-YK7/ClTt4kAK0vo6w3X+Pnm0D2cf2vPHbhOXdoNti1Ga0al1P4TBZhwjATvjNwLEBCnKvjJc2jQgHXH0NEwlAg==} + engines: {node: '>= 12.0.0'} + cpu: [arm64] + os: [android] + + lightningcss-darwin-arm64@1.32.0: + resolution: {integrity: sha512-RzeG9Ju5bag2Bv1/lwlVJvBE3q6TtXskdZLLCyfg5pt+HLz9BqlICO7LZM7VHNTTn/5PRhHFBSjk5lc4cmscPQ==} + engines: {node: '>= 12.0.0'} + cpu: [arm64] + os: [darwin] + + lightningcss-darwin-x64@1.32.0: + resolution: {integrity: sha512-U+QsBp2m/s2wqpUYT/6wnlagdZbtZdndSmut/NJqlCcMLTWp5muCrID+K5UJ6jqD2BFshejCYXniPDbNh73V8w==} + engines: {node: '>= 12.0.0'} + cpu: [x64] + os: [darwin] + + lightningcss-freebsd-x64@1.32.0: + resolution: {integrity: sha512-JCTigedEksZk3tHTTthnMdVfGf61Fky8Ji2E4YjUTEQX14xiy/lTzXnu1vwiZe3bYe0q+SpsSH/CTeDXK6WHig==} + engines: {node: '>= 12.0.0'} + cpu: [x64] + os: [freebsd] + + lightningcss-linux-arm-gnueabihf@1.32.0: + resolution: {integrity: sha512-x6rnnpRa2GL0zQOkt6rts3YDPzduLpWvwAF6EMhXFVZXD4tPrBkEFqzGowzCsIWsPjqSK+tyNEODUBXeeVHSkw==} + engines: {node: '>= 12.0.0'} + cpu: [arm] + os: [linux] + + lightningcss-linux-arm64-gnu@1.32.0: + resolution: {integrity: sha512-0nnMyoyOLRJXfbMOilaSRcLH3Jw5z9HDNGfT/gwCPgaDjnx0i8w7vBzFLFR1f6CMLKF8gVbebmkUN3fa/kQJpQ==} + engines: {node: '>= 12.0.0'} + cpu: [arm64] + os: [linux] + + lightningcss-linux-arm64-musl@1.32.0: + resolution: {integrity: sha512-UpQkoenr4UJEzgVIYpI80lDFvRmPVg6oqboNHfoH4CQIfNA+HOrZ7Mo7KZP02dC6LjghPQJeBsvXhJod/wnIBg==} + engines: {node: '>= 12.0.0'} + cpu: [arm64] + os: [linux] + + lightningcss-linux-x64-gnu@1.32.0: + resolution: {integrity: sha512-V7Qr52IhZmdKPVr+Vtw8o+WLsQJYCTd8loIfpDaMRWGUZfBOYEJeyJIkqGIDMZPwPx24pUMfwSxxI8phr/MbOA==} + engines: {node: '>= 12.0.0'} + cpu: [x64] + os: [linux] + + lightningcss-linux-x64-musl@1.32.0: + resolution: {integrity: sha512-bYcLp+Vb0awsiXg/80uCRezCYHNg1/l3mt0gzHnWV9XP1W5sKa5/TCdGWaR/zBM2PeF/HbsQv/j2URNOiVuxWg==} + engines: {node: '>= 12.0.0'} + cpu: [x64] + os: [linux] + + lightningcss-win32-arm64-msvc@1.32.0: + resolution: {integrity: sha512-8SbC8BR40pS6baCM8sbtYDSwEVQd4JlFTOlaD3gWGHfThTcABnNDBda6eTZeqbofalIJhFx0qKzgHJmcPTnGdw==} + engines: {node: '>= 12.0.0'} + cpu: [arm64] + os: [win32] + + lightningcss-win32-x64-msvc@1.32.0: + resolution: {integrity: sha512-Amq9B/SoZYdDi1kFrojnoqPLxYhQ4Wo5XiL8EVJrVsB8ARoC1PWW6VGtT0WKCemjy8aC+louJnjS7U18x3b06Q==} + engines: {node: '>= 12.0.0'} + cpu: [x64] + os: [win32] + + lightningcss@1.32.0: + resolution: {integrity: sha512-NXYBzinNrblfraPGyrbPoD19C1h9lfI/1mzgWYvXUTe414Gz/X1FD2XBZSZM7rRTrMA8JL3OtAaGifrIKhQ5yQ==} + engines: {node: '>= 12.0.0'} + locate-path@6.0.0: resolution: {integrity: sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==} engines: {node: '>=10'} @@ -1897,6 +2075,13 @@ packages: symbol-tree@3.2.4: resolution: {integrity: sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==} + tailwindcss@4.3.2: + resolution: {integrity: sha512-WtctNNSH8A9jlMIqxzuYumOHU5uGZyRv0Q5svQl+oEPy5w84YpBxdb7MdqyiSPQge5jTJ6zFQLq0PFygdccSBA==} + + tapable@2.3.3: + resolution: {integrity: sha512-uxc/zpqFg6x7C8vOE7lh6Lbda8eEL9zmVm/PLeTPBRhh1xCgdWaQ+J1CUieGpIfm2HdtsUpRv+HshiasBMcc6A==} + engines: {node: '>=6'} + tinybench@2.9.0: resolution: {integrity: sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg==} @@ -2444,9 +2629,9 @@ snapshots: '@esbuild/win32-x64@0.25.12': optional: true - '@eslint-community/eslint-utils@4.9.0(eslint@9.39.1)': + '@eslint-community/eslint-utils@4.9.0(eslint@9.39.1(jiti@2.7.0))': dependencies: - eslint: 9.39.1 + eslint: 9.39.1(jiti@2.7.0) eslint-visitor-keys: 3.4.3 '@eslint-community/regexpp@4.12.2': {} @@ -2673,11 +2858,11 @@ snapshots: '@standard-schema/spec@1.0.0': {} - '@stylistic/eslint-plugin@5.6.1(eslint@9.39.1)': + '@stylistic/eslint-plugin@5.6.1(eslint@9.39.1(jiti@2.7.0))': dependencies: - '@eslint-community/eslint-utils': 4.9.0(eslint@9.39.1) + '@eslint-community/eslint-utils': 4.9.0(eslint@9.39.1(jiti@2.7.0)) '@typescript-eslint/types': 8.49.0 - eslint: 9.39.1 + eslint: 9.39.1(jiti@2.7.0) eslint-visitor-keys: 4.2.1 espree: 10.4.0 estraverse: 5.3.0 @@ -2690,6 +2875,74 @@ snapshots: '@swc/counter': 0.1.3 tslib: 2.8.1 + '@tailwindcss/node@4.3.2': + dependencies: + '@jridgewell/remapping': 2.3.5 + enhanced-resolve: 5.21.6 + jiti: 2.7.0 + lightningcss: 1.32.0 + magic-string: 0.30.21 + source-map-js: 1.2.1 + tailwindcss: 4.3.2 + + '@tailwindcss/oxide-android-arm64@4.3.2': + optional: true + + '@tailwindcss/oxide-darwin-arm64@4.3.2': + optional: true + + '@tailwindcss/oxide-darwin-x64@4.3.2': + optional: true + + '@tailwindcss/oxide-freebsd-x64@4.3.2': + optional: true + + '@tailwindcss/oxide-linux-arm-gnueabihf@4.3.2': + optional: true + + '@tailwindcss/oxide-linux-arm64-gnu@4.3.2': + optional: true + + '@tailwindcss/oxide-linux-arm64-musl@4.3.2': + optional: true + + '@tailwindcss/oxide-linux-x64-gnu@4.3.2': + optional: true + + '@tailwindcss/oxide-linux-x64-musl@4.3.2': + optional: true + + '@tailwindcss/oxide-wasm32-wasi@4.3.2': + optional: true + + '@tailwindcss/oxide-win32-arm64-msvc@4.3.2': + optional: true + + '@tailwindcss/oxide-win32-x64-msvc@4.3.2': + optional: true + + '@tailwindcss/oxide@4.3.2': + optionalDependencies: + '@tailwindcss/oxide-android-arm64': 4.3.2 + '@tailwindcss/oxide-darwin-arm64': 4.3.2 + '@tailwindcss/oxide-darwin-x64': 4.3.2 + '@tailwindcss/oxide-freebsd-x64': 4.3.2 + '@tailwindcss/oxide-linux-arm-gnueabihf': 4.3.2 + '@tailwindcss/oxide-linux-arm64-gnu': 4.3.2 + '@tailwindcss/oxide-linux-arm64-musl': 4.3.2 + '@tailwindcss/oxide-linux-x64-gnu': 4.3.2 + '@tailwindcss/oxide-linux-x64-musl': 4.3.2 + '@tailwindcss/oxide-wasm32-wasi': 4.3.2 + '@tailwindcss/oxide-win32-arm64-msvc': 4.3.2 + '@tailwindcss/oxide-win32-x64-msvc': 4.3.2 + + '@tailwindcss/vite@4.3.2(vite@5.4.21(@types/node@20.19.26)(lightningcss@1.32.0))': + dependencies: + '@tailwindcss/node': 4.3.2 + '@tailwindcss/oxide': 4.3.2 + tailwindcss: 4.3.2 + vite: 5.4.21(@types/node@20.19.26)(lightningcss@1.32.0) + '@testing-library/dom@10.4.1': dependencies: '@babel/code-frame': 7.27.1 @@ -2759,15 +3012,15 @@ snapshots: '@types/resolve@1.20.2': {} - '@typescript-eslint/eslint-plugin@8.49.0(@typescript-eslint/parser@8.49.0(eslint@9.39.1)(typescript@5.9.3))(eslint@9.39.1)(typescript@5.9.3)': + '@typescript-eslint/eslint-plugin@8.49.0(@typescript-eslint/parser@8.49.0(eslint@9.39.1(jiti@2.7.0))(typescript@5.9.3))(eslint@9.39.1(jiti@2.7.0))(typescript@5.9.3)': dependencies: '@eslint-community/regexpp': 4.12.2 - '@typescript-eslint/parser': 8.49.0(eslint@9.39.1)(typescript@5.9.3) + '@typescript-eslint/parser': 8.49.0(eslint@9.39.1(jiti@2.7.0))(typescript@5.9.3) '@typescript-eslint/scope-manager': 8.49.0 - '@typescript-eslint/type-utils': 8.49.0(eslint@9.39.1)(typescript@5.9.3) - '@typescript-eslint/utils': 8.49.0(eslint@9.39.1)(typescript@5.9.3) + '@typescript-eslint/type-utils': 8.49.0(eslint@9.39.1(jiti@2.7.0))(typescript@5.9.3) + '@typescript-eslint/utils': 8.49.0(eslint@9.39.1(jiti@2.7.0))(typescript@5.9.3) '@typescript-eslint/visitor-keys': 8.49.0 - eslint: 9.39.1 + eslint: 9.39.1(jiti@2.7.0) ignore: 7.0.5 natural-compare: 1.4.0 ts-api-utils: 2.1.0(typescript@5.9.3) @@ -2775,14 +3028,14 @@ snapshots: transitivePeerDependencies: - supports-color - '@typescript-eslint/parser@8.49.0(eslint@9.39.1)(typescript@5.9.3)': + '@typescript-eslint/parser@8.49.0(eslint@9.39.1(jiti@2.7.0))(typescript@5.9.3)': dependencies: '@typescript-eslint/scope-manager': 8.49.0 '@typescript-eslint/types': 8.49.0 '@typescript-eslint/typescript-estree': 8.49.0(typescript@5.9.3) '@typescript-eslint/visitor-keys': 8.49.0 debug: 4.4.3 - eslint: 9.39.1 + eslint: 9.39.1(jiti@2.7.0) typescript: 5.9.3 transitivePeerDependencies: - supports-color @@ -2805,13 +3058,13 @@ snapshots: dependencies: typescript: 5.9.3 - '@typescript-eslint/type-utils@8.49.0(eslint@9.39.1)(typescript@5.9.3)': + '@typescript-eslint/type-utils@8.49.0(eslint@9.39.1(jiti@2.7.0))(typescript@5.9.3)': dependencies: '@typescript-eslint/types': 8.49.0 '@typescript-eslint/typescript-estree': 8.49.0(typescript@5.9.3) - '@typescript-eslint/utils': 8.49.0(eslint@9.39.1)(typescript@5.9.3) + '@typescript-eslint/utils': 8.49.0(eslint@9.39.1(jiti@2.7.0))(typescript@5.9.3) debug: 4.4.3 - eslint: 9.39.1 + eslint: 9.39.1(jiti@2.7.0) ts-api-utils: 2.1.0(typescript@5.9.3) typescript: 5.9.3 transitivePeerDependencies: @@ -2834,13 +3087,13 @@ snapshots: transitivePeerDependencies: - supports-color - '@typescript-eslint/utils@8.49.0(eslint@9.39.1)(typescript@5.9.3)': + '@typescript-eslint/utils@8.49.0(eslint@9.39.1(jiti@2.7.0))(typescript@5.9.3)': dependencies: - '@eslint-community/eslint-utils': 4.9.0(eslint@9.39.1) + '@eslint-community/eslint-utils': 4.9.0(eslint@9.39.1(jiti@2.7.0)) '@typescript-eslint/scope-manager': 8.49.0 '@typescript-eslint/types': 8.49.0 '@typescript-eslint/typescript-estree': 8.49.0(typescript@5.9.3) - eslint: 9.39.1 + eslint: 9.39.1(jiti@2.7.0) typescript: 5.9.3 transitivePeerDependencies: - supports-color @@ -2850,7 +3103,7 @@ snapshots: '@typescript-eslint/types': 8.49.0 eslint-visitor-keys: 4.2.1 - '@vitejs/plugin-react@4.7.0(vite@5.4.21(@types/node@20.19.26))': + '@vitejs/plugin-react@4.7.0(vite@5.4.21(@types/node@20.19.26)(lightningcss@1.32.0))': dependencies: '@babel/core': 7.28.5 '@babel/plugin-transform-react-jsx-self': 7.27.1(@babel/core@7.28.5) @@ -2858,33 +3111,33 @@ snapshots: '@rolldown/pluginutils': 1.0.0-beta.27 '@types/babel__core': 7.20.5 react-refresh: 0.17.0 - vite: 5.4.21(@types/node@20.19.26) + vite: 5.4.21(@types/node@20.19.26)(lightningcss@1.32.0) transitivePeerDependencies: - supports-color - '@vitest/browser-playwright@4.0.16(playwright@1.57.0)(vite@7.2.7(@types/node@20.19.26))(vitest@4.0.16)': + '@vitest/browser-playwright@4.0.16(playwright@1.57.0)(vite@7.2.7(@types/node@20.19.26)(jiti@2.7.0)(lightningcss@1.32.0))(vitest@4.0.16)': dependencies: - '@vitest/browser': 4.0.16(vite@7.2.7(@types/node@20.19.26))(vitest@4.0.16) - '@vitest/mocker': 4.0.16(vite@7.2.7(@types/node@20.19.26)) + '@vitest/browser': 4.0.16(vite@7.2.7(@types/node@20.19.26)(jiti@2.7.0)(lightningcss@1.32.0))(vitest@4.0.16) + '@vitest/mocker': 4.0.16(vite@7.2.7(@types/node@20.19.26)(jiti@2.7.0)(lightningcss@1.32.0)) playwright: 1.57.0 tinyrainbow: 3.0.3 - vitest: 4.0.16(@types/node@20.19.26)(@vitest/browser-playwright@4.0.16)(jsdom@27.4.0) + vitest: 4.0.16(@types/node@20.19.26)(@vitest/browser-playwright@4.0.16)(jiti@2.7.0)(jsdom@27.4.0)(lightningcss@1.32.0) transitivePeerDependencies: - bufferutil - msw - utf-8-validate - vite - '@vitest/browser@4.0.16(vite@7.2.7(@types/node@20.19.26))(vitest@4.0.16)': + '@vitest/browser@4.0.16(vite@7.2.7(@types/node@20.19.26)(jiti@2.7.0)(lightningcss@1.32.0))(vitest@4.0.16)': dependencies: - '@vitest/mocker': 4.0.16(vite@7.2.7(@types/node@20.19.26)) + '@vitest/mocker': 4.0.16(vite@7.2.7(@types/node@20.19.26)(jiti@2.7.0)(lightningcss@1.32.0)) '@vitest/utils': 4.0.16 magic-string: 0.30.21 pixelmatch: 7.1.0 pngjs: 7.0.0 sirv: 3.0.2 tinyrainbow: 3.0.3 - vitest: 4.0.16(@types/node@20.19.26)(@vitest/browser-playwright@4.0.16)(jsdom@27.4.0) + vitest: 4.0.16(@types/node@20.19.26)(@vitest/browser-playwright@4.0.16)(jiti@2.7.0)(jsdom@27.4.0)(lightningcss@1.32.0) ws: 8.18.3 transitivePeerDependencies: - bufferutil @@ -2901,13 +3154,13 @@ snapshots: chai: 6.2.1 tinyrainbow: 3.0.3 - '@vitest/mocker@4.0.16(vite@7.2.7(@types/node@20.19.26))': + '@vitest/mocker@4.0.16(vite@7.2.7(@types/node@20.19.26)(jiti@2.7.0)(lightningcss@1.32.0))': dependencies: '@vitest/spy': 4.0.16 estree-walker: 3.0.3 magic-string: 0.30.21 optionalDependencies: - vite: 7.2.7(@types/node@20.19.26) + vite: 7.2.7(@types/node@20.19.26)(jiti@2.7.0)(lightningcss@1.32.0) '@vitest/pretty-format@4.0.16': dependencies: @@ -3059,10 +3312,17 @@ snapshots: dequal@2.0.3: {} + detect-libc@2.1.2: {} + dom-accessibility-api@0.5.16: {} electron-to-chromium@1.5.267: {} + enhanced-resolve@5.21.6: + dependencies: + graceful-fs: 4.2.11 + tapable: 2.3.3 + entities@6.0.1: optional: true @@ -3136,9 +3396,9 @@ snapshots: eslint-visitor-keys@4.2.1: {} - eslint@9.39.1: + eslint@9.39.1(jiti@2.7.0): dependencies: - '@eslint-community/eslint-utils': 4.9.0(eslint@9.39.1) + '@eslint-community/eslint-utils': 4.9.0(eslint@9.39.1(jiti@2.7.0)) '@eslint-community/regexpp': 4.12.2 '@eslint/config-array': 0.21.1 '@eslint/config-helpers': 0.4.2 @@ -3172,6 +3432,8 @@ snapshots: minimatch: 3.1.2 natural-compare: 1.4.0 optionator: 0.9.4 + optionalDependencies: + jiti: 2.7.0 transitivePeerDependencies: - supports-color @@ -3314,6 +3576,8 @@ snapshots: isexe@2.0.0: {} + jiti@2.7.0: {} + js-tokens@4.0.0: {} js-yaml@4.1.1: @@ -3368,6 +3632,55 @@ snapshots: prelude-ls: 1.2.1 type-check: 0.4.0 + lightningcss-android-arm64@1.32.0: + optional: true + + lightningcss-darwin-arm64@1.32.0: + optional: true + + lightningcss-darwin-x64@1.32.0: + optional: true + + lightningcss-freebsd-x64@1.32.0: + optional: true + + lightningcss-linux-arm-gnueabihf@1.32.0: + optional: true + + lightningcss-linux-arm64-gnu@1.32.0: + optional: true + + lightningcss-linux-arm64-musl@1.32.0: + optional: true + + lightningcss-linux-x64-gnu@1.32.0: + optional: true + + lightningcss-linux-x64-musl@1.32.0: + optional: true + + lightningcss-win32-arm64-msvc@1.32.0: + optional: true + + lightningcss-win32-x64-msvc@1.32.0: + optional: true + + lightningcss@1.32.0: + dependencies: + detect-libc: 2.1.2 + optionalDependencies: + lightningcss-android-arm64: 1.32.0 + lightningcss-darwin-arm64: 1.32.0 + lightningcss-darwin-x64: 1.32.0 + lightningcss-freebsd-x64: 1.32.0 + lightningcss-linux-arm-gnueabihf: 1.32.0 + lightningcss-linux-arm64-gnu: 1.32.0 + lightningcss-linux-arm64-musl: 1.32.0 + lightningcss-linux-x64-gnu: 1.32.0 + lightningcss-linux-x64-musl: 1.32.0 + lightningcss-win32-arm64-msvc: 1.32.0 + lightningcss-win32-x64-msvc: 1.32.0 + locate-path@6.0.0: dependencies: p-locate: 5.0.0 @@ -3633,6 +3946,10 @@ snapshots: symbol-tree@3.2.4: optional: true + tailwindcss@4.3.2: {} + + tapable@2.3.3: {} + tinybench@2.9.0: {} tinyexec@1.0.2: {} @@ -3674,13 +3991,13 @@ snapshots: dependencies: prelude-ls: 1.2.1 - typescript-eslint@8.49.0(eslint@9.39.1)(typescript@5.9.3): + typescript-eslint@8.49.0(eslint@9.39.1(jiti@2.7.0))(typescript@5.9.3): dependencies: - '@typescript-eslint/eslint-plugin': 8.49.0(@typescript-eslint/parser@8.49.0(eslint@9.39.1)(typescript@5.9.3))(eslint@9.39.1)(typescript@5.9.3) - '@typescript-eslint/parser': 8.49.0(eslint@9.39.1)(typescript@5.9.3) + '@typescript-eslint/eslint-plugin': 8.49.0(@typescript-eslint/parser@8.49.0(eslint@9.39.1(jiti@2.7.0))(typescript@5.9.3))(eslint@9.39.1(jiti@2.7.0))(typescript@5.9.3) + '@typescript-eslint/parser': 8.49.0(eslint@9.39.1(jiti@2.7.0))(typescript@5.9.3) '@typescript-eslint/typescript-estree': 8.49.0(typescript@5.9.3) - '@typescript-eslint/utils': 8.49.0(eslint@9.39.1)(typescript@5.9.3) - eslint: 9.39.1 + '@typescript-eslint/utils': 8.49.0(eslint@9.39.1(jiti@2.7.0))(typescript@5.9.3) + eslint: 9.39.1(jiti@2.7.0) typescript: 5.9.3 transitivePeerDependencies: - supports-color @@ -3699,7 +4016,7 @@ snapshots: dependencies: punycode: 2.3.1 - vite@5.4.21(@types/node@20.19.26): + vite@5.4.21(@types/node@20.19.26)(lightningcss@1.32.0): dependencies: esbuild: 0.21.5 postcss: 8.5.6 @@ -3707,8 +4024,9 @@ snapshots: optionalDependencies: '@types/node': 20.19.26 fsevents: 2.3.3 + lightningcss: 1.32.0 - vite@7.2.7(@types/node@20.19.26): + vite@7.2.7(@types/node@20.19.26)(jiti@2.7.0)(lightningcss@1.32.0): dependencies: esbuild: 0.25.12 fdir: 6.5.0(picomatch@4.0.3) @@ -3719,11 +4037,13 @@ snapshots: optionalDependencies: '@types/node': 20.19.26 fsevents: 2.3.3 + jiti: 2.7.0 + lightningcss: 1.32.0 - vitest@4.0.16(@types/node@20.19.26)(@vitest/browser-playwright@4.0.16)(jsdom@27.4.0): + vitest@4.0.16(@types/node@20.19.26)(@vitest/browser-playwright@4.0.16)(jiti@2.7.0)(jsdom@27.4.0)(lightningcss@1.32.0): dependencies: '@vitest/expect': 4.0.16 - '@vitest/mocker': 4.0.16(vite@7.2.7(@types/node@20.19.26)) + '@vitest/mocker': 4.0.16(vite@7.2.7(@types/node@20.19.26)(jiti@2.7.0)(lightningcss@1.32.0)) '@vitest/pretty-format': 4.0.16 '@vitest/runner': 4.0.16 '@vitest/snapshot': 4.0.16 @@ -3740,11 +4060,11 @@ snapshots: tinyexec: 1.0.2 tinyglobby: 0.2.15 tinyrainbow: 3.0.3 - vite: 7.2.7(@types/node@20.19.26) + vite: 7.2.7(@types/node@20.19.26)(jiti@2.7.0)(lightningcss@1.32.0) why-is-node-running: 2.3.0 optionalDependencies: '@types/node': 20.19.26 - '@vitest/browser-playwright': 4.0.16(playwright@1.57.0)(vite@7.2.7(@types/node@20.19.26))(vitest@4.0.16) + '@vitest/browser-playwright': 4.0.16(playwright@1.57.0)(vite@7.2.7(@types/node@20.19.26)(jiti@2.7.0)(lightningcss@1.32.0))(vitest@4.0.16) jsdom: 27.4.0 transitivePeerDependencies: - jiti