@lerianstudio/sindarian-ui 2.0.0-beta.24 → 2.0.0-beta.26
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/charts/chart.js +4 -231
- package/dist/charts/index.js +1 -11
- package/dist/components/breadcrumb/get-breadcrumb-paths.js +1 -18
- package/dist/components/breadcrumb/index.js +1 -37
- package/dist/components/card/account-card/index.js +1 -69
- package/dist/components/card/basic-card/index.js +1 -20
- package/dist/components/card/dashboard-card/index.js +1 -20
- package/dist/components/card/entity-card/index.js +1 -68
- package/dist/components/card/index.js +1 -20
- package/dist/components/dialog/confirmation-dialog/index.d.ts.map +1 -1
- package/dist/components/dialog/confirmation-dialog/index.js +1 -96
- package/dist/components/dialog/confirmation-dialog/use-confirm-dialog.js +1 -55
- package/dist/components/dialog/index.js +1 -19
- package/dist/components/dialog/large-dialog/index.d.ts +2 -2
- package/dist/components/dialog/large-dialog/index.d.ts.map +1 -1
- package/dist/components/dialog/large-dialog/index.js +1 -21
- package/dist/components/entity-box/index.js +1 -67
- package/dist/components/entity-data-table/index.js +1 -20
- package/dist/components/form/combo-box-field/index.js +1 -35
- package/dist/components/form/country-field/index.js +1 -11
- package/dist/components/form/date-picker-field/index.js +1 -83
- package/dist/components/form/date-range-field/index.js +1 -58
- package/dist/components/form/date-time-picker-field/index.js +1 -114
- package/dist/components/form/file-upload-field/index.js +1 -69
- package/dist/components/form/index.js +1 -31
- package/dist/components/form/input-field/index.js +1 -96
- package/dist/components/form/otp-field/index.js +1 -19
- package/dist/components/form/pagination-limit-field/index.js +1 -10
- package/dist/components/form/password-field/index.d.ts.map +1 -1
- package/dist/components/form/password-field/index.js +1 -16
- package/dist/components/form/radio-group-field/index.js +1 -36
- package/dist/components/form/renderable-label.js +1 -57
- package/dist/components/form/select-field/index.js +1 -68
- package/dist/components/form/state-field/index.js +1 -42
- package/dist/components/form/switch-field/index.js +1 -16
- package/dist/components/form/textarea-field/index.js +1 -23
- package/dist/components/page/index.js +1 -20
- package/dist/components/page-header/index.js +1 -80
- package/dist/components/pagination/index.js +1 -10
- package/dist/components/table/id-table-cell.js +1 -109
- package/dist/components/table/index.js +1 -19
- package/dist/components/table/locked-table-actions.js +1 -41
- package/dist/components/table/name-table-cell.js +1 -58
- package/dist/components/ui/accordion/index.js +1 -62
- package/dist/components/ui/alert/index.js +1 -45
- package/dist/components/ui/alert-dialog/index.js +1 -84
- package/dist/components/ui/autocomplete/index.js +1 -440
- package/dist/components/ui/autosize-textarea/index.js +1 -89
- package/dist/components/ui/avatar/index.js +1 -51
- package/dist/components/ui/badge/index.js +1 -83
- package/dist/components/ui/breadcrumb/index.js +1 -35
- package/dist/components/ui/button/index.js +1 -65
- package/dist/components/ui/button/styles.css +2 -1
- package/dist/components/ui/calendar/index.js +1 -118
- package/dist/components/ui/card/index.js +1 -32
- package/dist/components/ui/checkbox/index.js +1 -44
- package/dist/components/ui/collapsible/index.js +1 -50
- package/dist/components/ui/command/index.js +1 -95
- package/dist/components/ui/copy-field/index.js +1 -163
- package/dist/components/ui/dialog/index.d.ts +4 -1
- package/dist/components/ui/dialog/index.d.ts.map +1 -1
- package/dist/components/ui/dialog/index.js +1 -80
- package/dist/components/ui/dialog/styles.css +2 -1
- package/dist/components/ui/dropdown-menu/index.js +1 -110
- package/dist/components/ui/field/index.js +1 -82
- package/dist/components/ui/file-upload/index.js +1 -574
- package/dist/components/ui/form.js +1 -162
- package/dist/components/ui/hover-card/index.js +1 -51
- package/dist/components/ui/icon-button/index.js +1 -35
- package/dist/components/ui/input/adornment.js +1 -21
- package/dist/components/ui/input/index.js +1 -99
- package/dist/components/ui/input/styles.css +29 -12
- package/dist/components/ui/label/index.js +1 -45
- package/dist/components/ui/lerian-wordmark/index.js +1 -7
- package/dist/components/ui/loading-button/index.js +1 -9
- package/dist/components/ui/multiple-select/index.js +1 -235
- package/dist/components/ui/otp-input/index.js +1 -62
- package/dist/components/ui/paper/index.js +1 -8
- package/dist/components/ui/paper-collapsible/index.js +1 -24
- package/dist/components/ui/popover/index.js +1 -55
- package/dist/components/ui/progress/index.js +1 -66
- package/dist/components/ui/qr-code/index.js +1 -27
- package/dist/components/ui/radio-group/index.js +1 -48
- package/dist/components/ui/scroll-area/index.js +1 -49
- package/dist/components/ui/select/index.js +1 -119
- package/dist/components/ui/select/styles.css +6 -3
- package/dist/components/ui/separator/index.js +1 -43
- package/dist/components/ui/sheet/index.d.ts +7 -2
- package/dist/components/ui/sheet/index.d.ts.map +1 -1
- package/dist/components/ui/sheet/index.js +1 -136
- package/dist/components/ui/sidebar/index.js +1 -27
- package/dist/components/ui/sidebar/next-router.cjs +1 -119
- package/dist/components/ui/sidebar/sidebar-back-button.js +1 -8
- package/dist/components/ui/sidebar/sidebar-components.js +1 -23
- package/dist/components/ui/sidebar/sidebar-expand-button.js +1 -49
- package/dist/components/ui/sidebar/sidebar-item-button.js +1 -21
- package/dist/components/ui/sidebar/sidebar-item-collapsible.js +1 -52
- package/dist/components/ui/sidebar/sidebar-item-icon-button.js +1 -18
- package/dist/components/ui/sidebar/sidebar-item.js +1 -44
- package/dist/components/ui/sidebar/sidebar-provider.js +1 -201
- package/dist/components/ui/sidebar/sidebar-root.d.ts +3 -1
- package/dist/components/ui/sidebar/sidebar-root.d.ts.map +1 -1
- package/dist/components/ui/sidebar/sidebar-root.js +1 -130
- package/dist/components/ui/sidebar/sidebar-router.js +1 -126
- package/dist/components/ui/sidebar/sidebar-trigger.js +1 -57
- package/dist/components/ui/skeleton/index.js +1 -8
- package/dist/components/ui/stepper/index.js +1 -29
- package/dist/components/ui/switch/index.js +1 -43
- package/dist/components/ui/table/index.js +1 -56
- package/dist/components/ui/tabs/index.js +1 -55
- package/dist/components/ui/textarea/index.js +1 -8
- package/dist/components/ui/time-picker/index.js +1 -85
- package/dist/components/ui/toast/index.js +1 -3
- package/dist/components/ui/toast/toaster.js +1 -16
- package/dist/components/ui/toggle-group/index.js +1 -156
- package/dist/components/ui/tooltip/index.js +1 -81
- package/dist/domain/blotter/index.js +1 -20
- package/dist/domain/delinquency-aging/aging-buckets.js +1 -120
- package/dist/domain/delinquency-aging/index.js +1 -222
- package/dist/domain/figure/index.js +1 -19
- package/dist/domain/format.js +1 -137
- package/dist/domain/index.js +1 -43
- package/dist/domain/key-id/index.js +1 -174
- package/dist/domain/ledger-sheet/index.js +1 -28
- package/dist/domain/money-diff.js +1 -48
- package/dist/domain/money-math.js +1 -104
- package/dist/domain/money-text/index.js +1 -123
- package/dist/domain/section-label/index.js +1 -17
- package/dist/domain/status-rail/index.js +1 -76
- package/dist/domain/threshold-gauge/index.js +1 -161
- package/dist/enterprise/alert-banner/index.js +1 -24
- package/dist/enterprise/app-shell/index.js +1 -87
- package/dist/enterprise/cursor-pager/index.js +1 -26
- package/dist/enterprise/data-table/column-size.js +1 -103
- package/dist/enterprise/data-table/index.d.ts.map +1 -1
- package/dist/enterprise/data-table/index.js +1 -345
- package/dist/enterprise/date-range-picker/index.js +1 -115
- package/dist/enterprise/detail-panel/index.js +1 -20
- package/dist/enterprise/empty-state/index.d.ts +6 -1
- package/dist/enterprise/empty-state/index.d.ts.map +1 -1
- package/dist/enterprise/empty-state/index.js +1 -13
- package/dist/enterprise/index.js +1 -39
- package/dist/enterprise/number-input/index.js +1 -252
- package/dist/enterprise/search-input/index.js +1 -121
- package/dist/enterprise/stat-card/index.js +1 -75
- package/dist/enterprise/status-badge/index.js +1 -120
- package/dist/enterprise/use-is-mobile.js +1 -68
- package/dist/enterprise/virtualized-table/index.js +1 -141
- package/dist/esm/charts/chart.js +4 -190
- package/dist/esm/charts/index.js +1 -3
- package/dist/esm/components/breadcrumb/get-breadcrumb-paths.js +1 -12
- package/dist/esm/components/breadcrumb/index.js +1 -30
- package/dist/esm/components/card/account-card/index.js +1 -53
- package/dist/esm/components/card/basic-card/index.js +1 -14
- package/dist/esm/components/card/dashboard-card/index.js +1 -14
- package/dist/esm/components/card/entity-card/index.js +1 -52
- package/dist/esm/components/card/index.js +1 -4
- package/dist/esm/components/dialog/confirmation-dialog/index.d.ts.map +1 -1
- package/dist/esm/components/dialog/confirmation-dialog/index.js +1 -60
- package/dist/esm/components/dialog/confirmation-dialog/use-confirm-dialog.js +1 -49
- package/dist/esm/components/dialog/index.js +1 -3
- package/dist/esm/components/dialog/large-dialog/index.d.ts +2 -2
- package/dist/esm/components/dialog/large-dialog/index.d.ts.map +1 -1
- package/dist/esm/components/dialog/large-dialog/index.js +1 -16
- package/dist/esm/components/entity-box/index.js +1 -56
- package/dist/esm/components/entity-data-table/index.js +1 -17
- package/dist/esm/components/form/combo-box-field/index.js +1 -28
- package/dist/esm/components/form/country-field/index.js +1 -7
- package/dist/esm/components/form/date-picker-field/index.js +1 -43
- package/dist/esm/components/form/date-range-field/index.js +1 -18
- package/dist/esm/components/form/date-time-picker-field/index.js +1 -74
- package/dist/esm/components/form/file-upload-field/index.js +1 -65
- package/dist/esm/components/form/index.js +1 -15
- package/dist/esm/components/form/input-field/index.js +1 -92
- package/dist/esm/components/form/otp-field/index.js +1 -15
- package/dist/esm/components/form/pagination-limit-field/index.js +1 -6
- package/dist/esm/components/form/password-field/index.d.ts.map +1 -1
- package/dist/esm/components/form/password-field/index.js +1 -10
- package/dist/esm/components/form/radio-group-field/index.js +1 -32
- package/dist/esm/components/form/renderable-label.js +1 -54
- package/dist/esm/components/form/select-field/index.js +1 -64
- package/dist/esm/components/form/state-field/index.js +1 -35
- package/dist/esm/components/form/switch-field/index.js +1 -12
- package/dist/esm/components/form/textarea-field/index.js +1 -19
- package/dist/esm/components/page/index.js +1 -15
- package/dist/esm/components/page-header/index.js +1 -71
- package/dist/esm/components/pagination/index.js +1 -6
- package/dist/esm/components/table/id-table-cell.js +1 -105
- package/dist/esm/components/table/index.js +1 -3
- package/dist/esm/components/table/locked-table-actions.js +1 -37
- package/dist/esm/components/table/name-table-cell.js +1 -54
- package/dist/esm/components/ui/accordion/index.js +1 -24
- package/dist/esm/components/ui/alert/index.js +1 -38
- package/dist/esm/components/ui/alert-dialog/index.js +1 -39
- package/dist/esm/components/ui/autocomplete/index.js +1 -392
- package/dist/esm/components/ui/autosize-textarea/index.js +1 -51
- package/dist/esm/components/ui/avatar/index.js +1 -14
- package/dist/esm/components/ui/badge/index.js +1 -79
- package/dist/esm/components/ui/breadcrumb/index.js +1 -27
- package/dist/esm/components/ui/button/index.js +1 -60
- package/dist/esm/components/ui/calendar/index.js +1 -82
- package/dist/esm/components/ui/card/index.js +1 -24
- package/dist/esm/components/ui/checkbox/index.js +1 -9
- package/dist/esm/components/ui/collapsible/index.js +1 -13
- package/dist/esm/components/ui/command/index.js +1 -51
- package/dist/esm/components/ui/copy-field/index.js +1 -127
- package/dist/esm/components/ui/dialog/index.d.ts +4 -1
- package/dist/esm/components/ui/dialog/index.d.ts.map +1 -1
- package/dist/esm/components/ui/dialog/index.js +1 -36
- package/dist/esm/components/ui/dropdown-menu/index.js +1 -60
- package/dist/esm/components/ui/field/index.js +1 -71
- package/dist/esm/components/ui/file-upload/index.js +1 -536
- package/dist/esm/components/ui/form.js +1 -118
- package/dist/esm/components/ui/hover-card/index.js +1 -14
- package/dist/esm/components/ui/icon-button/index.js +1 -31
- package/dist/esm/components/ui/input/adornment.js +1 -17
- package/dist/esm/components/ui/input/index.js +1 -60
- package/dist/esm/components/ui/label/index.js +1 -10
- package/dist/esm/components/ui/lerian-wordmark/index.js +1 -4
- package/dist/esm/components/ui/loading-button/index.js +1 -7
- package/dist/esm/components/ui/multiple-select/index.js +1 -196
- package/dist/esm/components/ui/otp-input/index.js +1 -21
- package/dist/esm/components/ui/paper/index.js +1 -5
- package/dist/esm/components/ui/paper-collapsible/index.js +1 -19
- package/dist/esm/components/ui/popover/index.js +1 -17
- package/dist/esm/components/ui/progress/index.js +1 -31
- package/dist/esm/components/ui/qr-code/index.js +1 -24
- package/dist/esm/components/ui/radio-group/index.js +1 -12
- package/dist/esm/components/ui/scroll-area/index.js +1 -13
- package/dist/esm/components/ui/select/index.js +1 -74
- package/dist/esm/components/ui/separator/index.js +1 -8
- package/dist/esm/components/ui/sheet/index.d.ts +7 -2
- package/dist/esm/components/ui/sheet/index.d.ts.map +1 -1
- package/dist/esm/components/ui/sheet/index.js +1 -92
- package/dist/esm/components/ui/sidebar/index.js +1 -11
- package/dist/esm/components/ui/sidebar/next-router.cjs +1 -119
- package/dist/esm/components/ui/sidebar/sidebar-back-button.js +1 -5
- package/dist/esm/components/ui/sidebar/sidebar-components.js +1 -15
- package/dist/esm/components/ui/sidebar/sidebar-expand-button.js +1 -42
- package/dist/esm/components/ui/sidebar/sidebar-item-button.js +1 -18
- package/dist/esm/components/ui/sidebar/sidebar-item-collapsible.js +1 -44
- package/dist/esm/components/ui/sidebar/sidebar-item-icon-button.js +1 -14
- package/dist/esm/components/ui/sidebar/sidebar-item.js +1 -40
- package/dist/esm/components/ui/sidebar/sidebar-provider.js +1 -193
- package/dist/esm/components/ui/sidebar/sidebar-root.d.ts +3 -1
- package/dist/esm/components/ui/sidebar/sidebar-root.d.ts.map +1 -1
- package/dist/esm/components/ui/sidebar/sidebar-root.js +1 -126
- package/dist/esm/components/ui/sidebar/sidebar-router.js +1 -89
- package/dist/esm/components/ui/sidebar/sidebar-trigger.js +1 -53
- package/dist/esm/components/ui/skeleton/index.js +1 -6
- package/dist/esm/components/ui/stepper/index.js +1 -20
- package/dist/esm/components/ui/switch/index.js +1 -8
- package/dist/esm/components/ui/table/index.js +1 -44
- package/dist/esm/components/ui/tabs/index.js +1 -17
- package/dist/esm/components/ui/textarea/index.js +1 -6
- package/dist/esm/components/ui/time-picker/index.js +1 -49
- package/dist/esm/components/ui/toast/index.js +1 -2
- package/dist/esm/components/ui/toast/toaster.js +1 -13
- package/dist/esm/components/ui/toggle-group/index.js +1 -120
- package/dist/esm/components/ui/tooltip/index.js +1 -43
- package/dist/esm/domain/blotter/index.js +1 -16
- package/dist/esm/domain/delinquency-aging/aging-buckets.js +1 -115
- package/dist/esm/domain/delinquency-aging/index.js +1 -218
- package/dist/esm/domain/figure/index.js +1 -15
- package/dist/esm/domain/format.js +1 -128
- package/dist/esm/domain/index.js +1 -19
- package/dist/esm/domain/key-id/index.js +1 -169
- package/dist/esm/domain/ledger-sheet/index.js +1 -24
- package/dist/esm/domain/money-diff.js +1 -45
- package/dist/esm/domain/money-math.js +1 -98
- package/dist/esm/domain/money-text/index.js +1 -118
- package/dist/esm/domain/section-label/index.js +1 -14
- package/dist/esm/domain/status-rail/index.js +1 -71
- package/dist/esm/domain/threshold-gauge/index.js +1 -157
- package/dist/esm/enterprise/alert-banner/index.js +1 -21
- package/dist/esm/enterprise/app-shell/index.js +1 -51
- package/dist/esm/enterprise/cursor-pager/index.js +1 -23
- package/dist/esm/enterprise/data-table/column-size.js +1 -97
- package/dist/esm/enterprise/data-table/index.d.ts.map +1 -1
- package/dist/esm/enterprise/data-table/index.js +1 -342
- package/dist/esm/enterprise/date-range-picker/index.js +1 -112
- package/dist/esm/enterprise/detail-panel/index.js +1 -17
- package/dist/esm/enterprise/empty-state/index.d.ts +6 -1
- package/dist/esm/enterprise/empty-state/index.d.ts.map +1 -1
- package/dist/esm/enterprise/empty-state/index.js +1 -10
- package/dist/esm/enterprise/index.js +1 -22
- package/dist/esm/enterprise/number-input/index.js +1 -214
- package/dist/esm/enterprise/search-input/index.js +1 -85
- package/dist/esm/enterprise/stat-card/index.js +1 -72
- package/dist/esm/enterprise/status-badge/index.js +1 -116
- package/dist/esm/enterprise/use-is-mobile.js +1 -31
- package/dist/esm/enterprise/virtualized-table/index.js +1 -138
- package/dist/esm/hooks/use-click-away.js +1 -22
- package/dist/esm/hooks/use-pagination.js +1 -38
- package/dist/esm/hooks/use-stepper.js +1 -22
- package/dist/esm/hooks/use-time.js +1 -13
- package/dist/esm/hooks/use-toast.js +1 -107
- package/dist/esm/index.js +1 -77
- package/dist/esm/lib/storage/get-storage-object.js +1 -17
- package/dist/esm/lib/storage/get-storage.js +1 -14
- package/dist/esm/lib/storage/index.js +1 -2
- package/dist/esm/lib/typography.js +1 -31
- package/dist/esm/lib/utils.js +1 -41
- package/dist/esm/theme/get-theme-script.js +1 -41
- package/dist/esm/theme/index.js +1 -4
- package/dist/esm/theme/mode-toggle.js +1 -45
- package/dist/esm/theme/theme-provider.js +1 -122
- package/dist/esm/toast/helpers.js +1 -36
- package/dist/esm/toast/index.js +1 -4
- package/dist/esm/types/metadata-type.js +1 -1
- package/dist/esm/utils/countries.cjs +1 -17
- package/dist/esm/utils/country-utils.js +1 -18
- package/dist/esm/utils/currency-codes.js +1 -181
- package/dist/globals.css +1 -0
- package/dist/hooks/use-click-away.js +1 -29
- package/dist/hooks/use-pagination.js +1 -41
- package/dist/hooks/use-stepper.js +1 -26
- package/dist/hooks/use-time.js +1 -20
- package/dist/hooks/use-toast.js +1 -111
- package/dist/index.js +1 -96
- package/dist/lib/storage/get-storage-object.js +1 -23
- package/dist/lib/storage/get-storage.js +1 -17
- package/dist/lib/storage/index.js +1 -18
- package/dist/lib/typography.js +1 -34
- package/dist/lib/utils.js +1 -45
- package/dist/theme/get-theme-script.js +1 -44
- package/dist/theme/index.js +1 -11
- package/dist/theme/mode-toggle.js +1 -48
- package/dist/theme/theme-provider.js +1 -160
- package/dist/toast/helpers.js +1 -41
- package/dist/toast/index.js +1 -10
- package/dist/tokens.css +7 -4
- package/dist/types/metadata-type.js +1 -2
- package/dist/utils/countries.cjs +1 -17
- package/dist/utils/country-utils.js +1 -25
- package/dist/utils/currency-codes.js +1 -184
- package/package.json +4 -3
|
@@ -1,138 +1 @@
|
|
|
1
|
-
|
|
2
|
-
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
-
/**
|
|
4
|
-
* VirtualizedTable — a windowed table for very large, flat datasets.
|
|
5
|
-
*
|
|
6
|
-
* Mirrors DataTable's column/data API (standard TanStack `ColumnDef<T>`, cells
|
|
7
|
-
* receive the row's `original`), so screens reuse the exact same column
|
|
8
|
-
* definitions. The difference is the rendering strategy: where DataTable
|
|
9
|
-
* renders every row, VirtualizedTable renders only the rows inside (and just
|
|
10
|
-
* past) the scroll viewport via `@tanstack/react-virtual`. Tens of thousands of
|
|
11
|
-
* rows stay scroll-smooth because the DOM only ever holds the visible window.
|
|
12
|
-
*
|
|
13
|
-
* Layout is div-based (role="table"/"row"/"cell"), not a real `<table>`:
|
|
14
|
-
* absolute positioning by `virtualItem.start` is incompatible with table
|
|
15
|
-
* layout, so a windowed table cannot use `<tbody>`. The header is a sibling
|
|
16
|
-
* above the scroll region: it stays put by layout (it simply sits above an
|
|
17
|
-
* overflow box), not via `position: sticky`. Inside the scroll container an
|
|
18
|
-
* inner spacer sized to `getTotalSize()` reserves the full scroll height, and
|
|
19
|
-
* each virtual row is absolutely positioned within that spacer.
|
|
20
|
-
*
|
|
21
|
-
* Rows are fixed-height (= `rowHeight`): cell content taller than `rowHeight`
|
|
22
|
-
* will clip — cells use `truncate`. This component is for flat, single-line
|
|
23
|
-
* datasets only; it does NOT measure rows, so it is not suitable for
|
|
24
|
-
* variable-height content.
|
|
25
|
-
*
|
|
26
|
-
* This is deliberately leaner than DataTable: no pagination, selection,
|
|
27
|
-
* keyboard nav, loading or empty affordances — it is the right tool only when
|
|
28
|
-
* the whole dataset is already in memory and the row count is the problem.
|
|
29
|
-
* For server-paged lists, reach for DataTable + CursorPager instead.
|
|
30
|
-
*/
|
|
31
|
-
import { useEffect, useRef, useState } from 'react';
|
|
32
|
-
import { flexRender, getCoreRowModel, useReactTable } from '@tanstack/react-table';
|
|
33
|
-
import { useVirtualizer } from '@tanstack/react-virtual';
|
|
34
|
-
import { LABEL_VOICE_CLASS } from '../../lib/typography.js';
|
|
35
|
-
import { cn } from '../../lib/utils.js';
|
|
36
|
-
import { readDeclaredColumnSize, readDeclaredGroupSize, UNSIZED_DEFAULT_COLUMN } from '../data-table/column-size.js';
|
|
37
|
-
/** Rows rendered just outside the viewport to keep fast scrolls smooth. */
|
|
38
|
-
const OVERSCAN = 8;
|
|
39
|
-
export function VirtualizedTable({ columns, data, rowHeight = 40, maxHeight = 480, scrollAreaLabel = 'Scrollable table rows', className, headClassName }) {
|
|
40
|
-
const scrollRef = useRef(null);
|
|
41
|
-
const [isScrollable, setIsScrollable] = useState(false);
|
|
42
|
-
// A number is px; a string is used verbatim (e.g. '60vh').
|
|
43
|
-
const viewportMaxHeight = typeof maxHeight === 'number' ? `${maxHeight}px` : maxHeight;
|
|
44
|
-
const table = useReactTable({
|
|
45
|
-
data,
|
|
46
|
-
columns,
|
|
47
|
-
// Keeps `columnDef.size`/`minSize`/`maxSize` meaning "declared" — see
|
|
48
|
-
// ../data-table/column-size. `getSize()` is unaffected; it falls back to
|
|
49
|
-
// the library defaults itself.
|
|
50
|
-
defaultColumn: UNSIZED_DEFAULT_COLUMN,
|
|
51
|
-
getCoreRowModel: getCoreRowModel()
|
|
52
|
-
});
|
|
53
|
-
const rows = table.getRowModel().rows;
|
|
54
|
-
// Grouped columns (a ColumnDef with nested `columns`) render one header row
|
|
55
|
-
// per depth level, so the header is not always a single row.
|
|
56
|
-
const headerGroups = table.getHeaderGroups();
|
|
57
|
-
const headerRowCount = headerGroups.length;
|
|
58
|
-
// The table's real column geometry is its LEAF columns: a grouped ColumnDef
|
|
59
|
-
// contributes one spanning header cell but no column of its own, so counting
|
|
60
|
-
// top-level defs both under-reports aria-colcount and misplaces every
|
|
61
|
-
// aria-colindex to its right.
|
|
62
|
-
const leafColumns = table.getVisibleLeafColumns();
|
|
63
|
-
const leafPosition = new Map(leafColumns.map((column, i) => [column.id, i]));
|
|
64
|
-
const virtualizer = useVirtualizer({
|
|
65
|
-
count: rows.length,
|
|
66
|
-
getScrollElement: () => scrollRef.current,
|
|
67
|
-
estimateSize: () => rowHeight,
|
|
68
|
-
overscan: OVERSCAN
|
|
69
|
-
});
|
|
70
|
-
const virtualRows = virtualizer.getVirtualItems();
|
|
71
|
-
const totalSize = virtualizer.getTotalSize();
|
|
72
|
-
// `estimateSize` is read through a closure the virtualizer caches per item, so
|
|
73
|
-
// changing rowHeight leaves every already-measured row at its old size until
|
|
74
|
-
// the cache is dropped explicitly.
|
|
75
|
-
useEffect(() => {
|
|
76
|
-
virtualizer.measure();
|
|
77
|
-
}, [rowHeight, virtualizer]);
|
|
78
|
-
useEffect(() => {
|
|
79
|
-
const viewport = scrollRef.current;
|
|
80
|
-
if (!viewport)
|
|
81
|
-
return;
|
|
82
|
-
const updateScrollability = () => {
|
|
83
|
-
const nextIsScrollable = viewport.scrollHeight > viewport.clientHeight ||
|
|
84
|
-
viewport.scrollWidth > viewport.clientWidth;
|
|
85
|
-
setIsScrollable((current) => current === nextIsScrollable ? current : nextIsScrollable);
|
|
86
|
-
};
|
|
87
|
-
updateScrollability();
|
|
88
|
-
if (typeof ResizeObserver === 'undefined')
|
|
89
|
-
return;
|
|
90
|
-
const observer = new ResizeObserver(updateScrollability);
|
|
91
|
-
observer.observe(viewport);
|
|
92
|
-
const content = viewport.firstElementChild;
|
|
93
|
-
if (content)
|
|
94
|
-
observer.observe(content);
|
|
95
|
-
return () => observer.disconnect();
|
|
96
|
-
}, [totalSize, viewportMaxHeight]);
|
|
97
|
-
return (_jsx("div", { className: cn('border-border bg-card text-card-foreground rounded-lg border', className), children: _jsxs("div", { role: "table", "aria-rowcount": rows.length + headerRowCount, "aria-colcount": leafColumns.length, children: [_jsx("div", { role: "rowgroup", className: "bg-card z-10", children: headerGroups.map((headerGroup, groupIndex) => (_jsx("div", { role: "row", "aria-rowindex": groupIndex + 1, className: "border-border flex border-b", children: headerGroup.headers.map((header) => {
|
|
98
|
-
// Anchor the cell on its leftmost leaf column, so a spanning
|
|
99
|
-
// group reports the column it actually starts at rather than
|
|
100
|
-
// its position among its siblings.
|
|
101
|
-
const firstLeaf = header.column.getLeafColumns()[0];
|
|
102
|
-
const start = leafPosition.get(firstLeaf?.id ?? header.column.id);
|
|
103
|
-
// A group header spans leaf columns whose body cells carry
|
|
104
|
-
// their own widths, so its size comes from those leaves, not
|
|
105
|
-
// from the group def (which declares nothing). A leaf header
|
|
106
|
-
// reads its own column, as before.
|
|
107
|
-
const size = header.subHeaders.length > 0
|
|
108
|
-
? readDeclaredGroupSize(header.column.getLeafColumns())
|
|
109
|
-
: readDeclaredColumnSize(header.column);
|
|
110
|
-
return (_jsx("div", { role: "columnheader", "aria-colindex": (start ?? 0) + 1, "aria-colspan": header.colSpan > 1 ? header.colSpan : undefined,
|
|
111
|
-
// A declared width must not be flexed away; without one the
|
|
112
|
-
// cell keeps its colSpan share of the row, as before.
|
|
113
|
-
style: size?.width === undefined
|
|
114
|
-
? { flex: `${header.colSpan} 1 0%`, ...size }
|
|
115
|
-
: { flex: '0 0 auto', ...size },
|
|
116
|
-
// Header height is independent of rowHeight: pinning it to a
|
|
117
|
-
// small rowHeight (32) clipped the uppercase label against its
|
|
118
|
-
// own padding. Padding sizes it; min-h keeps a stable rule.
|
|
119
|
-
className: cn('min-h-10 px-4 py-2.5 text-left', LABEL_VOICE_CLASS, headClassName), children: header.isPlaceholder
|
|
120
|
-
? null
|
|
121
|
-
: flexRender(header.column.columnDef.header, header.getContext()) }, header.id));
|
|
122
|
-
}) }, headerGroup.id))) }), _jsx("div", { ref: scrollRef, role: "rowgroup", "data-testid": "virtualized-table-viewport", "aria-label": isScrollable ? scrollAreaLabel : undefined, tabIndex: isScrollable ? 0 : undefined, className: "focus-visible:ring-ring relative overflow-auto focus-visible:ring-2 focus-visible:ring-offset-2 focus-visible:outline-none", style: { maxHeight: viewportMaxHeight }, children: _jsx("div", { role: "presentation", className: "relative w-full", style: { height: totalSize }, children: virtualRows.map((virtualItem) => {
|
|
123
|
-
const row = rows[virtualItem.index];
|
|
124
|
-
return (_jsx("div", { role: "row", "aria-rowindex": virtualItem.index + headerRowCount + 1, "data-index": virtualItem.index, className: "border-border absolute left-0 flex w-full items-center border-b text-sm", style: {
|
|
125
|
-
height: virtualItem.size,
|
|
126
|
-
transform: `translateY(${virtualItem.start}px)`
|
|
127
|
-
}, children: row.getVisibleCells().map((cell, i) => {
|
|
128
|
-
const size = readDeclaredColumnSize(cell.column);
|
|
129
|
-
return (_jsx("div", { role: "cell", "aria-colindex": i + 1,
|
|
130
|
-
// An inline `flex` beats the class, so a sized column
|
|
131
|
-
// stops flexing while every other column renders
|
|
132
|
-
// exactly as it did before.
|
|
133
|
-
style: size?.width === undefined
|
|
134
|
-
? size
|
|
135
|
-
: { flex: '0 0 auto', ...size }, className: "flex-1 truncate px-4", children: flexRender(cell.column.columnDef.cell, cell.getContext()) }, cell.id));
|
|
136
|
-
}) }, row.id));
|
|
137
|
-
}) }) })] }) }));
|
|
138
|
-
}
|
|
1
|
+
"use client";import{jsx as l,jsxs as M}from"react/jsx-runtime";import{useEffect as v,useRef as _,useState as O}from"react";import{flexRender as h,getCoreRowModel as j,useReactTable as A}from"@tanstack/react-table";import{useVirtualizer as T}from"@tanstack/react-virtual";import{LABEL_VOICE_CLASS as H}from"../../lib/typography.js";import{cn as S}from"../../lib/utils.js";import{readDeclaredColumnSize as C,readDeclaredGroupSize as U,UNSIZED_DEFAULT_COLUMN as $}from"../data-table/column-size.js";const G=8;export function VirtualizedTable({columns:z,data:R,rowHeight:f=40,maxHeight:a=480,scrollAreaLabel:N="Scrollable table rows",className:y,headClassName:L}){const c=_(null);const[m,E]=O(false);const b=typeof a==="number"?`${a}px`:a;const d=A({data:R,columns:z,defaultColumn:$,getCoreRowModel:j()});const u=d.getRowModel().rows;const p=d.getHeaderGroups();const g=p.length;const x=d.getVisibleLeafColumns();const V=new Map(x.map((o,t)=>[o.id,t]));const s=T({count:u.length,getScrollElement:()=>c.current,estimateSize:()=>f,overscan:G});const D=s.getVirtualItems();const w=s.getTotalSize();v(()=>{s.measure()},[f,s]);v(()=>{const o=c.current;if(!o)return;const t=()=>{const r=o.scrollHeight>o.clientHeight||o.scrollWidth>o.clientWidth;E(i=>i===r?i:r)};t();if(typeof ResizeObserver==="undefined")return;const e=new ResizeObserver(t);e.observe(o);const n=o.firstElementChild;if(n)e.observe(n);return()=>e.disconnect()},[w,b]);return l("div",{className:S("border-border bg-card text-card-foreground rounded-lg border",y),children:M("div",{role:"table","aria-rowcount":u.length+g,"aria-colcount":x.length,children:[l("div",{role:"rowgroup",className:"bg-card z-10",children:p.map((o,t)=>l("div",{role:"row","aria-rowindex":t+1,className:"border-border flex border-b",children:o.headers.map(e=>{const n=e.column.getLeafColumns()[0];const r=V.get(n?.id??e.column.id);const i=e.subHeaders.length>0?U(e.column.getLeafColumns()):C(e.column);return l("div",{role:"columnheader","aria-colindex":(r??0)+1,"aria-colspan":e.colSpan>1?e.colSpan:void 0,style:i?.width===void 0?{flex:`${e.colSpan} 1 0%`,...i}:{flex:"0 0 auto",...i},className:S("min-h-10 px-4 py-2.5 text-left",H,L),children:e.isPlaceholder?null:h(e.column.columnDef.header,e.getContext())},e.id)})},o.id))}),l("div",{ref:c,role:"rowgroup","data-testid":"virtualized-table-viewport","aria-label":m?N:void 0,tabIndex:m?0:void 0,className:"focus-visible:ring-ring relative overflow-auto focus-visible:ring-2 focus-visible:ring-offset-2 focus-visible:outline-none",style:{maxHeight:b},children:l("div",{role:"presentation",className:"relative w-full",style:{height:w},children:D.map(o=>{const t=u[o.index];return l("div",{role:"row","aria-rowindex":o.index+g+1,"data-index":o.index,className:"border-border absolute left-0 flex w-full items-center border-b text-sm",style:{height:o.size,transform:`translateY(${o.start}px)`},children:t.getVisibleCells().map((e,n)=>{const r=C(e.column);return l("div",{role:"cell","aria-colindex":n+1,style:r?.width===void 0?r:{flex:"0 0 auto",...r},className:"flex-1 truncate px-4",children:h(e.column.columnDef.cell,e.getContext())},e.id)})},t.id)})})})]})})}
|
|
@@ -1,22 +1 @@
|
|
|
1
|
-
import
|
|
2
|
-
/**
|
|
3
|
-
* Detects clicks outside of a specified component and triggers a callback function.
|
|
4
|
-
*
|
|
5
|
-
* @param ref Component reference
|
|
6
|
-
* @param onClickAway Callback function to be called when a click is detected outside the component
|
|
7
|
-
*/
|
|
8
|
-
export const useClickAway = (ref, onClickAway) => {
|
|
9
|
-
const handleClick = React.useCallback((event) => {
|
|
10
|
-
if (ref.current && !ref.current.contains(event.target)) {
|
|
11
|
-
onClickAway(event);
|
|
12
|
-
}
|
|
13
|
-
}, [ref, onClickAway]);
|
|
14
|
-
React.useEffect(() => {
|
|
15
|
-
document.addEventListener('mousedown', handleClick);
|
|
16
|
-
document.addEventListener('touchend', handleClick);
|
|
17
|
-
return () => {
|
|
18
|
-
document.removeEventListener('mousedown', handleClick);
|
|
19
|
-
document.removeEventListener('touchend', handleClick);
|
|
20
|
-
};
|
|
21
|
-
}, [ref, handleClick]);
|
|
22
|
-
};
|
|
1
|
+
import c from"react";export const useClickAway=(t,n)=>{const e=c.useCallback(o=>{if(t.current&&!t.current.contains(o.target)){n(o)}},[t,n]);c.useEffect(()=>{document.addEventListener("mousedown",e);document.addEventListener("touchend",e);return()=>{document.removeEventListener("mousedown",e);document.removeEventListener("touchend",e)}},[t,e])};
|
|
@@ -1,38 +1 @@
|
|
|
1
|
-
import {
|
|
2
|
-
export function usePagination({ total = 1 }) {
|
|
3
|
-
const [page, _setPage] = useState(1);
|
|
4
|
-
const [limit, _setLimit] = useState(10);
|
|
5
|
-
const totalPages = Math.ceil(total / limit);
|
|
6
|
-
const nextPage = () => {
|
|
7
|
-
if (page + 1 > totalPages) {
|
|
8
|
-
return;
|
|
9
|
-
}
|
|
10
|
-
_setPage((page) => page + 1);
|
|
11
|
-
};
|
|
12
|
-
const previousPage = () => {
|
|
13
|
-
if (page - 1 < 1) {
|
|
14
|
-
return;
|
|
15
|
-
}
|
|
16
|
-
_setPage((page) => page - 1);
|
|
17
|
-
};
|
|
18
|
-
const setPage = (page) => {
|
|
19
|
-
if (page < 1 || page > totalPages) {
|
|
20
|
-
return;
|
|
21
|
-
}
|
|
22
|
-
_setPage(page);
|
|
23
|
-
};
|
|
24
|
-
const setLimit = (limit) => {
|
|
25
|
-
if (limit < 1) {
|
|
26
|
-
return;
|
|
27
|
-
}
|
|
28
|
-
_setLimit(limit);
|
|
29
|
-
};
|
|
30
|
-
return {
|
|
31
|
-
page,
|
|
32
|
-
limit,
|
|
33
|
-
setLimit,
|
|
34
|
-
setPage,
|
|
35
|
-
nextPage,
|
|
36
|
-
previousPage
|
|
37
|
-
};
|
|
38
|
-
}
|
|
1
|
+
import{useState as o}from"react";export function usePagination({total:r=1}){const[e,n]=o(1);const[s,a]=o(10);const i=Math.ceil(r/s);const c=()=>{if(e+1>i){return}n(t=>t+1)};const u=()=>{if(e-1<1){return}n(t=>t-1)};const f=t=>{if(t<1||t>i){return}n(t)};const P=t=>{if(t<1){return}a(t)};return{page:e,limit:s,setLimit:P,setPage:f,nextPage:c,previousPage:u}}
|
|
@@ -1,22 +1 @@
|
|
|
1
|
-
import
|
|
2
|
-
export const useStepper = ({ defaultStep = 0, maxSteps = 2 }) => {
|
|
3
|
-
const [step, setStep] = useState(defaultStep);
|
|
4
|
-
const handleNext = () => {
|
|
5
|
-
if (maxSteps && step >= maxSteps - 1) {
|
|
6
|
-
return;
|
|
7
|
-
}
|
|
8
|
-
setStep((prev) => prev + 1);
|
|
9
|
-
};
|
|
10
|
-
const handlePrevious = () => {
|
|
11
|
-
if (step <= 0) {
|
|
12
|
-
return;
|
|
13
|
-
}
|
|
14
|
-
setStep((prev) => prev - 1);
|
|
15
|
-
};
|
|
16
|
-
return {
|
|
17
|
-
step,
|
|
18
|
-
setStep,
|
|
19
|
-
handleNext,
|
|
20
|
-
handlePrevious
|
|
21
|
-
};
|
|
22
|
-
};
|
|
1
|
+
import{useState as p}from"react";export const useStepper=({defaultStep:o=0,maxSteps:n=2})=>{const[e,t]=p(o);const s=()=>{if(n&&e>=n-1){return}t(r=>r+1)};const u=()=>{if(e<=0){return}t(r=>r-1)};return{step:e,setStep:t,handleNext:s,handlePrevious:u}};
|
|
@@ -1,13 +1 @@
|
|
|
1
|
-
import
|
|
2
|
-
export const useTime = ({ interval = 1000, onUpdate }) => {
|
|
3
|
-
const [time, setTime] = React.useState(new Date());
|
|
4
|
-
React.useEffect(() => {
|
|
5
|
-
const timer = setInterval(() => {
|
|
6
|
-
const newTime = new Date();
|
|
7
|
-
setTime(newTime);
|
|
8
|
-
onUpdate?.(newTime);
|
|
9
|
-
}, interval);
|
|
10
|
-
return () => clearInterval(timer);
|
|
11
|
-
}, [interval, onUpdate]);
|
|
12
|
-
return time;
|
|
13
|
-
};
|
|
1
|
+
import n from"react";export const useTime=({interval:e=1e3,onUpdate:t})=>{const[s,c]=n.useState(new Date);n.useEffect(()=>{const m=setInterval(()=>{const r=new Date;c(r);t?.(r)},e);return()=>clearInterval(m)},[e,t]);return s};
|
|
@@ -1,107 +1 @@
|
|
|
1
|
-
|
|
2
|
-
import { toast as sonnerToast } from 'sonner';
|
|
3
|
-
/**
|
|
4
|
-
* Lifetime of every non-destructive toast, and the `<Toaster />` fallback for
|
|
5
|
-
* anything raised without one. The two must not drift apart, so the Toaster
|
|
6
|
-
* imports this rather than repeating the literal.
|
|
7
|
-
*/
|
|
8
|
-
export const DEFAULT_DURATION = 10000;
|
|
9
|
-
/**
|
|
10
|
-
* A destructive toast reports something the operator has to read -- a refused
|
|
11
|
-
* money operation, a failed copy of a show-once secret, a language switch that
|
|
12
|
-
* did not take. It stays up until dismissed instead of auto-closing.
|
|
13
|
-
*
|
|
14
|
-
* `Infinity` is how sonner disables the auto-close timer (it short-circuits the
|
|
15
|
-
* timer effect rather than calling `setTimeout(fn, Infinity)`, which would fire
|
|
16
|
-
* immediately). `<Toaster />` already passes `closeButton`, and sonner gates the
|
|
17
|
-
* close button on that flag alone, never on the duration -- so a persistent
|
|
18
|
-
* toast still renders its dismiss affordance.
|
|
19
|
-
*/
|
|
20
|
-
const PERSIST_UNTIL_DISMISSED = Infinity;
|
|
21
|
-
const isPlainText = (value) => value === undefined || typeof value === 'string';
|
|
22
|
-
/**
|
|
23
|
-
* Two identical errors share one toast instead of stacking: same variant, same
|
|
24
|
-
* text -- same id, and sonner updates the one already on screen.
|
|
25
|
-
*
|
|
26
|
-
* Unbounded stacking is worse for a persistent toast than for a transient one.
|
|
27
|
-
* `<Toaster />` shows three at a time and renders the rest `opacity: 0;
|
|
28
|
-
* pointer-events: none`, so a fourth error nobody can read is also a fourth
|
|
29
|
-
* error nobody can close -- and without an auto-dismiss, nothing ahead of it
|
|
30
|
-
* clears on its own.
|
|
31
|
-
*
|
|
32
|
-
* Only plain-text toasts collapse. A `ReactNode` has no stable key and
|
|
33
|
-
* `String(node)` would fold unrelated errors onto one id.
|
|
34
|
-
*
|
|
35
|
-
* ponytail: the ceiling is still three. Distinct persistent errors past the
|
|
36
|
-
* third queue behind the front three until one is dismissed; lifting that means
|
|
37
|
-
* raising `visibleToasts`, not more work here.
|
|
38
|
-
*/
|
|
39
|
-
function collapseKey(title, description) {
|
|
40
|
-
if (!isPlainText(title) || !isPlainText(description)) {
|
|
41
|
-
return undefined;
|
|
42
|
-
}
|
|
43
|
-
return `destructive:${JSON.stringify([title ?? null, description ?? null])}`;
|
|
44
|
-
}
|
|
45
|
-
function toast({ title, description, variant, duration, id, ...rest }) {
|
|
46
|
-
const message = title ?? '';
|
|
47
|
-
const toastId = variant === 'destructive' && id === undefined
|
|
48
|
-
? collapseKey(title, description)
|
|
49
|
-
: id;
|
|
50
|
-
const options = {
|
|
51
|
-
description,
|
|
52
|
-
...rest,
|
|
53
|
-
...(toastId !== undefined && { id: toastId }),
|
|
54
|
-
duration: duration ??
|
|
55
|
-
(variant === 'destructive' ? PERSIST_UNTIL_DISMISSED : DEFAULT_DURATION)
|
|
56
|
-
};
|
|
57
|
-
let raisedId;
|
|
58
|
-
switch (variant) {
|
|
59
|
-
case 'success':
|
|
60
|
-
raisedId = sonnerToast.success(message, options);
|
|
61
|
-
break;
|
|
62
|
-
case 'warning':
|
|
63
|
-
raisedId = sonnerToast.warning(message, options);
|
|
64
|
-
break;
|
|
65
|
-
case 'destructive':
|
|
66
|
-
raisedId = sonnerToast.error(message, options);
|
|
67
|
-
break;
|
|
68
|
-
default:
|
|
69
|
-
raisedId = sonnerToast(message, options);
|
|
70
|
-
break;
|
|
71
|
-
}
|
|
72
|
-
return {
|
|
73
|
-
id: raisedId,
|
|
74
|
-
dismiss: () => sonnerToast.dismiss(raisedId),
|
|
75
|
-
update: (props) => {
|
|
76
|
-
sonnerToast(props.title ?? message, {
|
|
77
|
-
...rest,
|
|
78
|
-
id: raisedId,
|
|
79
|
-
description: props.description ?? description,
|
|
80
|
-
duration: props.duration ?? options.duration
|
|
81
|
-
});
|
|
82
|
-
}
|
|
83
|
-
};
|
|
84
|
-
}
|
|
85
|
-
/**
|
|
86
|
-
* Backward-compatible hook that wraps Sonner's toast API.
|
|
87
|
-
*
|
|
88
|
-
* Returns the same shape as the original Radix-based useToast:
|
|
89
|
-
* - `toast()` to create a toast
|
|
90
|
-
* - `dismiss()` to dismiss a toast by id (or all if no id)
|
|
91
|
-
* - `toasts` array (always empty -- Sonner manages its own state internally)
|
|
92
|
-
*/
|
|
93
|
-
function useToast() {
|
|
94
|
-
return {
|
|
95
|
-
toast,
|
|
96
|
-
dismiss: (toastId) => {
|
|
97
|
-
if (toastId !== undefined) {
|
|
98
|
-
sonnerToast.dismiss(toastId);
|
|
99
|
-
}
|
|
100
|
-
else {
|
|
101
|
-
sonnerToast.dismiss();
|
|
102
|
-
}
|
|
103
|
-
},
|
|
104
|
-
toasts: []
|
|
105
|
-
};
|
|
106
|
-
}
|
|
107
|
-
export { useToast, toast };
|
|
1
|
+
"use client";import{toast as e}from"sonner";export const DEFAULT_DURATION=1e4;const I=Infinity;const f=s=>s===void 0||typeof s==="string";function T(s,t){if(!f(s)||!f(t)){return void 0}return`destructive:${JSON.stringify([s??null,t??null])}`}function l({title:s,description:t,variant:r,duration:m,id:o,...c}){const i=s??"";const a=r==="destructive"&&o===void 0?T(s,t):o;const d={description:t,...c,...a!==void 0&&{id:a},duration:m??(r==="destructive"?I:DEFAULT_DURATION)};let n;switch(r){case"success":n=e.success(i,d);break;case"warning":n=e.warning(i,d);break;case"destructive":n=e.error(i,d);break;default:n=e(i,d);break}return{id:n,dismiss:()=>e.dismiss(n),update:u=>{e(u.title??i,{...c,id:n,description:u.description??t,duration:u.duration??d.duration})}}}function S(){return{toast:l,dismiss:s=>{if(s!==void 0){e.dismiss(s)}else{e.dismiss()}},toasts:[]}}export{S as useToast,l as toast};
|
package/dist/esm/index.js
CHANGED
|
@@ -1,77 +1 @@
|
|
|
1
|
-
|
|
2
|
-
// Primitives
|
|
3
|
-
export * from './components/ui/alert/index.js';
|
|
4
|
-
export * from './components/ui/autocomplete/index.js';
|
|
5
|
-
export * from './hooks/use-click-away.js';
|
|
6
|
-
export * from './components/ui/autosize-textarea/index.js';
|
|
7
|
-
export * from './components/ui/avatar/index.js';
|
|
8
|
-
export * from './components/ui/badge/index.js';
|
|
9
|
-
export * from './components/ui/breadcrumb/index.js';
|
|
10
|
-
export * from './components/ui/button/index.js';
|
|
11
|
-
export * from './components/ui/icon-button/index.js';
|
|
12
|
-
export * from './components/ui/calendar/index.js';
|
|
13
|
-
export * from './components/ui/card/index.js';
|
|
14
|
-
export * from './components/ui/checkbox/index.js';
|
|
15
|
-
export * from './components/ui/collapsible/index.js';
|
|
16
|
-
export * from './components/ui/command/index.js';
|
|
17
|
-
export * from './components/ui/copy-field/index.js';
|
|
18
|
-
export * from './components/ui/dialog/index.js';
|
|
19
|
-
export * from './components/ui/dropdown-menu/index.js';
|
|
20
|
-
export * from './components/ui/input/index.js';
|
|
21
|
-
export * from './components/ui/otp-input/index.js';
|
|
22
|
-
export * from './components/ui/label/index.js';
|
|
23
|
-
export * from './components/ui/lerian-wordmark/index.js';
|
|
24
|
-
export * from './components/ui/loading-button/index.js';
|
|
25
|
-
export * from './components/ui/multiple-select/index.js';
|
|
26
|
-
export * from './components/ui/paper/index.js';
|
|
27
|
-
export * from './components/ui/paper-collapsible/index.js';
|
|
28
|
-
export * from './components/ui/popover/index.js';
|
|
29
|
-
export * from './components/ui/progress/index.js';
|
|
30
|
-
export * from './components/ui/qr-code/index.js';
|
|
31
|
-
export * from './components/ui/select/index.js';
|
|
32
|
-
export * from './components/ui/separator/index.js';
|
|
33
|
-
export * from './components/ui/sheet/index.js';
|
|
34
|
-
export * from './components/ui/sidebar/index.js';
|
|
35
|
-
export * from './components/ui/skeleton/index.js';
|
|
36
|
-
export * from './components/ui/stepper/index.js';
|
|
37
|
-
export * from './hooks/use-stepper.js';
|
|
38
|
-
export * from './components/ui/switch/index.js';
|
|
39
|
-
export * from './components/ui/table/index.js';
|
|
40
|
-
export * from './components/ui/tabs/index.js';
|
|
41
|
-
export * from './components/ui/textarea/index.js';
|
|
42
|
-
export * from './components/ui/toast/index.js';
|
|
43
|
-
export * from './components/ui/toast/toaster.js';
|
|
44
|
-
export * from './hooks/use-toast.js';
|
|
45
|
-
export * from './components/ui/time-picker/index.js';
|
|
46
|
-
export * from './hooks/use-time.js';
|
|
47
|
-
export * from './components/ui/tooltip/index.js';
|
|
48
|
-
export * from './components/ui/form.js';
|
|
49
|
-
// Components
|
|
50
|
-
export { Breadcrumb as ApplicationBreadcrumb } from './components/breadcrumb/index.js';
|
|
51
|
-
export * from './components/breadcrumb/get-breadcrumb-paths.js';
|
|
52
|
-
export * from './components/card/index.js';
|
|
53
|
-
export * from './components/dialog/index.js';
|
|
54
|
-
export * from './components/entity-box/index.js';
|
|
55
|
-
export * from './components/entity-data-table/index.js';
|
|
56
|
-
export * from './components/form/index.js';
|
|
57
|
-
export * from './components/page/index.js';
|
|
58
|
-
export * from './components/page-header/index.js';
|
|
59
|
-
export * from './components/pagination/index.js';
|
|
60
|
-
export * from './components/table/index.js';
|
|
61
|
-
// Enterprise surface (sindarian-x absorption — see docs/plans/2026-08-26-sindarian-x-retirement/)
|
|
62
|
-
export * from './enterprise/index.js';
|
|
63
|
-
export * from './theme/index.js';
|
|
64
|
-
export * from './toast/index.js';
|
|
65
|
-
export * from './charts/index.js';
|
|
66
|
-
export * from './domain/index.js';
|
|
67
|
-
// Primitives absorbed from sindarian-x (see docs/plans/2026-08-26-sindarian-x-retirement/)
|
|
68
|
-
export * from './components/ui/accordion/index.js';
|
|
69
|
-
export * from './components/ui/alert-dialog/index.js';
|
|
70
|
-
export * from './components/ui/file-upload/index.js';
|
|
71
|
-
export * from './components/ui/hover-card/index.js';
|
|
72
|
-
export * from './components/ui/radio-group/index.js';
|
|
73
|
-
export * from './components/ui/scroll-area/index.js';
|
|
74
|
-
export * from './components/ui/toggle-group/index.js';
|
|
75
|
-
// Utilities
|
|
76
|
-
export { cn } from './lib/utils.js';
|
|
77
|
-
export * from './lib/typography.js';
|
|
1
|
+
"use client";export*from"./components/ui/alert/index.js";export*from"./components/ui/autocomplete/index.js";export*from"./hooks/use-click-away.js";export*from"./components/ui/autosize-textarea/index.js";export*from"./components/ui/avatar/index.js";export*from"./components/ui/badge/index.js";export*from"./components/ui/breadcrumb/index.js";export*from"./components/ui/button/index.js";export*from"./components/ui/icon-button/index.js";export*from"./components/ui/calendar/index.js";export*from"./components/ui/card/index.js";export*from"./components/ui/checkbox/index.js";export*from"./components/ui/collapsible/index.js";export*from"./components/ui/command/index.js";export*from"./components/ui/copy-field/index.js";export*from"./components/ui/dialog/index.js";export*from"./components/ui/dropdown-menu/index.js";export*from"./components/ui/input/index.js";export*from"./components/ui/otp-input/index.js";export*from"./components/ui/label/index.js";export*from"./components/ui/lerian-wordmark/index.js";export*from"./components/ui/loading-button/index.js";export*from"./components/ui/multiple-select/index.js";export*from"./components/ui/paper/index.js";export*from"./components/ui/paper-collapsible/index.js";export*from"./components/ui/popover/index.js";export*from"./components/ui/progress/index.js";export*from"./components/ui/qr-code/index.js";export*from"./components/ui/select/index.js";export*from"./components/ui/separator/index.js";export*from"./components/ui/sheet/index.js";export*from"./components/ui/sidebar/index.js";export*from"./components/ui/skeleton/index.js";export*from"./components/ui/stepper/index.js";export*from"./hooks/use-stepper.js";export*from"./components/ui/switch/index.js";export*from"./components/ui/table/index.js";export*from"./components/ui/tabs/index.js";export*from"./components/ui/textarea/index.js";export*from"./components/ui/toast/index.js";export*from"./components/ui/toast/toaster.js";export*from"./hooks/use-toast.js";export*from"./components/ui/time-picker/index.js";export*from"./hooks/use-time.js";export*from"./components/ui/tooltip/index.js";export*from"./components/ui/form.js";export{Breadcrumb as ApplicationBreadcrumb}from"./components/breadcrumb/index.js";export*from"./components/breadcrumb/get-breadcrumb-paths.js";export*from"./components/card/index.js";export*from"./components/dialog/index.js";export*from"./components/entity-box/index.js";export*from"./components/entity-data-table/index.js";export*from"./components/form/index.js";export*from"./components/page/index.js";export*from"./components/page-header/index.js";export*from"./components/pagination/index.js";export*from"./components/table/index.js";export*from"./enterprise/index.js";export*from"./theme/index.js";export*from"./toast/index.js";export*from"./charts/index.js";export*from"./domain/index.js";export*from"./components/ui/accordion/index.js";export*from"./components/ui/alert-dialog/index.js";export*from"./components/ui/file-upload/index.js";export*from"./components/ui/hover-card/index.js";export*from"./components/ui/radio-group/index.js";export*from"./components/ui/scroll-area/index.js";export*from"./components/ui/toggle-group/index.js";export{cn}from"./lib/utils.js";export*from"./lib/typography.js";
|
|
@@ -1,17 +1 @@
|
|
|
1
|
-
import
|
|
2
|
-
import isEmpty from 'lodash/isEmpty.js';
|
|
3
|
-
import isNil from 'lodash/isNil.js';
|
|
4
|
-
export function getStorageObject(key, defaultValue) {
|
|
5
|
-
try {
|
|
6
|
-
const dataString = getStorage(key, defaultValue);
|
|
7
|
-
const isNilOrEmpty = isNil(dataString) || isEmpty(dataString);
|
|
8
|
-
return isNilOrEmpty ? {} : JSON.parse(dataString);
|
|
9
|
-
}
|
|
10
|
-
catch (error) {
|
|
11
|
-
// Only log errors when not in test environment
|
|
12
|
-
if (process.env.NODE_ENV !== 'test') {
|
|
13
|
-
console.error(error);
|
|
14
|
-
}
|
|
15
|
-
return defaultValue;
|
|
16
|
-
}
|
|
17
|
-
}
|
|
1
|
+
import{getStorage as i}from"./get-storage.js";import s from"lodash/isEmpty.js";import n from"lodash/isNil.js";export function getStorageObject(o,t){try{const r=i(o,t);const e=n(r)||s(r);return e?{}:JSON.parse(r)}catch(r){if(process.env.NODE_ENV!=="test"){console.error(r)}return t}}
|
|
@@ -1,14 +1 @@
|
|
|
1
|
-
const
|
|
2
|
-
export function getStorage(key, defaultValue) {
|
|
3
|
-
if (isServer) {
|
|
4
|
-
return defaultValue;
|
|
5
|
-
}
|
|
6
|
-
let value;
|
|
7
|
-
try {
|
|
8
|
-
value = localStorage.getItem(key) || undefined;
|
|
9
|
-
}
|
|
10
|
-
catch (_e) {
|
|
11
|
-
// Unsupported
|
|
12
|
-
}
|
|
13
|
-
return value || defaultValue;
|
|
14
|
-
}
|
|
1
|
+
const r=typeof window==="undefined";export function getStorage(n,e){if(r){return e}let t;try{t=localStorage.getItem(n)||void 0}catch(o){}return t||e}
|
|
@@ -1,2 +1 @@
|
|
|
1
|
-
export
|
|
2
|
-
export * from './get-storage-object.js';
|
|
1
|
+
export*from"./get-storage.js";export*from"./get-storage-object.js";
|
|
@@ -1,31 +1 @@
|
|
|
1
|
-
|
|
2
|
-
* THE canonical quiet-label voice: sentence-case, one step down in size,
|
|
3
|
-
* medium weight, muted ink. Used by column heads, panel headings, key/value
|
|
4
|
-
* labels, captions — anywhere the console needs a quiet label.
|
|
5
|
-
*
|
|
6
|
-
* This is product-console's table-head voice, copied rather than invented. The
|
|
7
|
-
* kit's own `TableHead` paints `text-muted-foreground … font-medium` inside a
|
|
8
|
-
* `text-sm` `Table` (`components/ui/table/index.tsx:20,90`), and
|
|
9
|
-
* product-console renders every data table through that primitive
|
|
10
|
-
* (`src/components/table/data-table.tsx:14`). It replaced the retired "Ledger"
|
|
11
|
-
* voice — `text-[11px] uppercase tracking-[0.08em]` — which shouted a register
|
|
12
|
-
* no sibling console speaks.
|
|
13
|
-
*
|
|
14
|
-
* Do NOT re-state the cluster by hand; compose extra classes via
|
|
15
|
-
* `cn(LABEL_VOICE_CLASS, ...)`.
|
|
16
|
-
*/
|
|
17
|
-
export const LABEL_VOICE_CLASS = 'text-sm font-medium text-muted-foreground';
|
|
18
|
-
/**
|
|
19
|
-
* Alias of {@link LABEL_VOICE_CLASS} for section headings. Kept as a distinct
|
|
20
|
-
* name so section-level headings can diverge later without touching every
|
|
21
|
-
* quiet-label call site.
|
|
22
|
-
*
|
|
23
|
-
* It stays an alias on purpose. product-console's panel/section TITLE voice is
|
|
24
|
-
* `text-muted-foreground text-lg font-medium` (`EntityBoxHeaderTitle`,
|
|
25
|
-
* `components/entity-box/index.tsx:108`) — but that voice already ships as a
|
|
26
|
-
* component, and every live `SectionLabel` call site is a caption or a small
|
|
27
|
-
* heading (a stat-card label, an inline rate label), not an EntityBox-scale
|
|
28
|
-
* panel title. Promoting this constant to `text-lg` would duplicate a voice the
|
|
29
|
-
* kit already owns and inflate those captions.
|
|
30
|
-
*/
|
|
31
|
-
export const SECTION_LABEL_CLASS = LABEL_VOICE_CLASS;
|
|
1
|
+
export const LABEL_VOICE_CLASS="text-sm font-medium text-muted-foreground";export const SECTION_LABEL_CLASS=LABEL_VOICE_CLASS;
|
package/dist/esm/lib/utils.js
CHANGED
|
@@ -1,41 +1 @@
|
|
|
1
|
-
import
|
|
2
|
-
import { extendTailwindMerge } from 'tailwind-merge';
|
|
3
|
-
/**
|
|
4
|
-
* The kit's button variants are component classes in `@layer components`, not
|
|
5
|
-
* Tailwind utilities, so stock tailwind-merge has no group for them: it kept
|
|
6
|
-
* `button-primary button-destructive` together and let stylesheet source order
|
|
7
|
-
* pick the winner. Declaring the group makes the last one win, like every other
|
|
8
|
-
* conflict `cn` resolves.
|
|
9
|
-
*
|
|
10
|
-
* Variant classes only. `button-base`, `button-disabled`, `button-read-only`
|
|
11
|
-
* and `button-small` compose with a variant instead of conflicting with it, so
|
|
12
|
-
* they stay out of the group and are never merged away.
|
|
13
|
-
*/
|
|
14
|
-
const twMerge = extendTailwindMerge({
|
|
15
|
-
extend: {
|
|
16
|
-
classGroups: {
|
|
17
|
-
'sindarian-button-variant': [
|
|
18
|
-
'button-plain',
|
|
19
|
-
'button-primary',
|
|
20
|
-
'button-secondary',
|
|
21
|
-
'button-tertiary',
|
|
22
|
-
'button-outline',
|
|
23
|
-
'button-link',
|
|
24
|
-
'button-destructive'
|
|
25
|
-
]
|
|
26
|
-
}
|
|
27
|
-
}
|
|
28
|
-
});
|
|
29
|
-
export function cn(...inputs) {
|
|
30
|
-
return twMerge(clsx(inputs));
|
|
31
|
-
}
|
|
32
|
-
/** Wraps a Radix `onInteractOutside` so a press on a toast never dismisses the layer under it. */
|
|
33
|
-
export function keepOpenOnToast(onInteractOutside) {
|
|
34
|
-
return (event) => {
|
|
35
|
-
if (event.target?.closest('[data-sonner-toaster]')) {
|
|
36
|
-
event.preventDefault();
|
|
37
|
-
return;
|
|
38
|
-
}
|
|
39
|
-
onInteractOutside?.(event);
|
|
40
|
-
};
|
|
41
|
-
}
|
|
1
|
+
import{clsx as r}from"clsx";import{extendTailwindMerge as e}from"tailwind-merge";const o=e({extend:{classGroups:{"sindarian-button-variant":["button-plain","button-primary","button-secondary","button-tertiary","button-outline","button-link","button-destructive"]}}});export function cn(...t){return o(r(t))}export function keepOpenOnToast(t){return n=>{if(n.target?.closest("[data-sonner-toaster]")){n.preventDefault();return}t?.(n)}}
|
|
@@ -1,41 +1 @@
|
|
|
1
|
-
|
|
2
|
-
* Pre-paint theme script (FOUC guard). Returns a minified IIFE string that
|
|
3
|
-
* reads the persisted preference from localStorage, resolves it the way
|
|
4
|
-
* ThemeProvider does, and toggles the `.dark` class on the page root element
|
|
5
|
-
* before first paint — so the page never flashes the wrong theme while React
|
|
6
|
-
* hydrates. ThemeProvider owns the class from mount onward.
|
|
7
|
-
*
|
|
8
|
-
* The resolution mirrors ThemeProvider's exactly: an exact "dark"/"light"/
|
|
9
|
-
* "system" stored value wins; anything else — absent or corrupted — falls back
|
|
10
|
-
* to `defaultTheme`, which is then resolved ("dark" → dark, "light" → light,
|
|
11
|
-
* "system" → the media query). Pass the SAME `defaultTheme` you give
|
|
12
|
-
* ThemeProvider, or the two disagree on a first visit.
|
|
13
|
-
* `get-theme-script.test.tsx` pins that agreement case by case.
|
|
14
|
-
*
|
|
15
|
-
* Server-safe: this module references no browser globals at module scope; the
|
|
16
|
-
* returned string runs in the browser only, inside a try/catch.
|
|
17
|
-
*
|
|
18
|
-
* Consumer usage — inject in the page <head>, ideally as the first script:
|
|
19
|
-
*
|
|
20
|
-
* <script dangerouslySetInnerHTML={{ __html: getThemeScript() }} />
|
|
21
|
-
*
|
|
22
|
-
* A dark-by-default app passes both arguments:
|
|
23
|
-
*
|
|
24
|
-
* <script dangerouslySetInnerHTML={{ __html: getThemeScript('app.theme', 'dark') }} />
|
|
25
|
-
*/
|
|
26
|
-
/**
|
|
27
|
-
* JSON string literal with `<` escaped, so no embedded value can close the
|
|
28
|
-
* inline <script> element it is written into. `<` is `<` to the JS parser,
|
|
29
|
-
* so the emitted script still compares against the original text.
|
|
30
|
-
*/
|
|
31
|
-
function jsString(value) {
|
|
32
|
-
return JSON.stringify(value).replace(/</g, '\\u003C');
|
|
33
|
-
}
|
|
34
|
-
export function getThemeScript(storageKey = 'sindarian.theme', defaultTheme = 'system') {
|
|
35
|
-
// The storage read gets its OWN try/catch, mirroring ThemeProvider, which
|
|
36
|
-
// isolates the same read. A browser with site data blocked throws on
|
|
37
|
-
// getItem; if that escaped to the outer catch the class would never be
|
|
38
|
-
// applied at all and a dark user would flash light before hydration.
|
|
39
|
-
// Resolution starts from defaultTheme and storage only narrows it.
|
|
40
|
-
return `(function(){try{var r=${jsString(defaultTheme)};try{var t=localStorage.getItem(${jsString(storageKey)});if(t==="dark"||t==="light"||t==="system")r=t}catch(e){}var d=r==="dark"||(r==="system"&&matchMedia("(prefers-color-scheme: dark)").matches);document.documentElement.classList.toggle("dark",d)}catch(e){}})()`;
|
|
41
|
-
}
|
|
1
|
+
function e(t){return JSON.stringify(t).replace(/</g,"\\u003C")}export function getThemeScript(t="sindarian.theme",r="system"){return`(function(){try{var r=${e(r)};try{var t=localStorage.getItem(${e(t)});if(t==="dark"||t==="light"||t==="system")r=t}catch(e){}var d=r==="dark"||(r==="system"&&matchMedia("(prefers-color-scheme: dark)").matches);document.documentElement.classList.toggle("dark",d)}catch(e){}})()`}
|
package/dist/esm/theme/index.js
CHANGED
|
@@ -1,4 +1 @@
|
|
|
1
|
-
|
|
2
|
-
export { ThemeProvider, useTheme } from './theme-provider.js';
|
|
3
|
-
export { getThemeScript } from './get-theme-script.js';
|
|
4
|
-
export { ModeToggle } from './mode-toggle.js';
|
|
1
|
+
export{ThemeProvider,useTheme}from"./theme-provider.js";export{getThemeScript}from"./get-theme-script.js";export{ModeToggle}from"./mode-toggle.js";
|