tempest-react-sdk 0.24.0 → 0.26.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +25 -4
- package/bin/lib/alias/collect.mjs +94 -0
- package/bin/lib/alias/collect.test.mjs +95 -0
- package/bin/lib/alias/discover.mjs +77 -0
- package/bin/lib/alias/discover.test.mjs +189 -0
- package/bin/lib/alias/index.mjs +88 -0
- package/bin/lib/alias/index.test.mjs +138 -0
- package/bin/lib/alias/rewrite-css.mjs +76 -0
- package/bin/lib/alias/rewrite-css.test.mjs +85 -0
- package/bin/lib/alias/rewrite.mjs +141 -0
- package/bin/lib/alias/rewrite.test.mjs +148 -0
- package/bin/lib/alias/specifier.mjs +49 -0
- package/bin/lib/alias/specifier.test.mjs +85 -0
- package/bin/lib/alias/tsconfig.mjs +116 -0
- package/bin/lib/alias/typescript.mjs +23 -0
- package/bin/lib/icons/generate.mjs +156 -0
- package/bin/lib/icons/generate.test.mjs +125 -0
- package/bin/tempest.mjs +158 -13
- package/dist/audio/use-audio.cjs +1 -1
- package/dist/audio/use-audio.cjs.map +1 -1
- package/dist/audio/use-audio.js +12 -12
- package/dist/audio/use-audio.js.map +1 -1
- package/dist/charts/AreaChart.cjs +1 -1
- package/dist/charts/AreaChart.cjs.map +1 -1
- package/dist/charts/AreaChart.js +7 -7
- package/dist/charts/AreaChart.js.map +1 -1
- package/dist/charts/BarChart.cjs +1 -1
- package/dist/charts/BarChart.cjs.map +1 -1
- package/dist/charts/BarChart.js +7 -7
- package/dist/charts/BarChart.js.map +1 -1
- package/dist/charts/LineChart.cjs +1 -1
- package/dist/charts/LineChart.cjs.map +1 -1
- package/dist/charts/LineChart.js +6 -6
- package/dist/charts/LineChart.js.map +1 -1
- package/dist/charts/PieChart.cjs +1 -1
- package/dist/charts/PieChart.cjs.map +1 -1
- package/dist/charts/PieChart.js +6 -6
- package/dist/charts/PieChart.js.map +1 -1
- package/dist/charts/RadarChart.cjs +1 -1
- package/dist/charts/RadarChart.cjs.map +1 -1
- package/dist/charts/RadarChart.js +6 -6
- package/dist/charts/RadarChart.js.map +1 -1
- package/dist/charts/palette.cjs +1 -1
- package/dist/charts/palette.cjs.map +1 -1
- package/dist/charts/palette.js +19 -2
- package/dist/charts/palette.js.map +1 -1
- package/dist/charts/use-chart-colors.cjs +2 -0
- package/dist/charts/use-chart-colors.cjs.map +1 -0
- package/dist/charts/use-chart-colors.js +29 -0
- package/dist/charts/use-chart-colors.js.map +1 -0
- package/dist/charts.cjs +1 -1
- package/dist/charts.d.ts +61 -10
- package/dist/charts.js +8 -7
- package/dist/components/AvatarGroup/AvatarGroup.cjs +2 -0
- package/dist/components/AvatarGroup/AvatarGroup.cjs.map +1 -0
- package/dist/components/AvatarGroup/AvatarGroup.js +39 -0
- package/dist/components/AvatarGroup/AvatarGroup.js.map +1 -0
- package/dist/components/AvatarGroup/AvatarGroup.module.cjs +2 -0
- package/dist/components/AvatarGroup/AvatarGroup.module.cjs.map +1 -0
- package/dist/components/AvatarGroup/AvatarGroup.module.js +16 -0
- package/dist/components/AvatarGroup/AvatarGroup.module.js.map +1 -0
- package/dist/components/ClickOutside/ClickOutside.cjs +1 -1
- package/dist/components/ClickOutside/ClickOutside.cjs.map +1 -1
- package/dist/components/ClickOutside/ClickOutside.js +3 -1
- package/dist/components/ClickOutside/ClickOutside.js.map +1 -1
- package/dist/components/DataTable/DataTable.cjs +1 -1
- package/dist/components/DataTable/DataTable.cjs.map +1 -1
- package/dist/components/DataTable/DataTable.js +21 -23
- package/dist/components/DataTable/DataTable.js.map +1 -1
- package/dist/components/Kanban/Kanban.cjs +2 -0
- package/dist/components/Kanban/Kanban.cjs.map +1 -0
- package/dist/components/Kanban/Kanban.js +102 -0
- package/dist/components/Kanban/Kanban.js.map +1 -0
- package/dist/components/Kanban/Kanban.module.cjs +2 -0
- package/dist/components/Kanban/Kanban.module.cjs.map +1 -0
- package/dist/components/Kanban/Kanban.module.js +19 -0
- package/dist/components/Kanban/Kanban.module.js.map +1 -0
- package/dist/components/Lightbox/Lightbox.cjs +2 -0
- package/dist/components/Lightbox/Lightbox.cjs.map +1 -0
- package/dist/components/Lightbox/Lightbox.js +148 -0
- package/dist/components/Lightbox/Lightbox.js.map +1 -0
- package/dist/components/Lightbox/Lightbox.module.cjs +2 -0
- package/dist/components/Lightbox/Lightbox.module.cjs.map +1 -0
- package/dist/components/Lightbox/Lightbox.module.js +21 -0
- package/dist/components/Lightbox/Lightbox.module.js.map +1 -0
- package/dist/components/NotificationCenter/NotificationCenter.cjs +2 -0
- package/dist/components/NotificationCenter/NotificationCenter.cjs.map +1 -0
- package/dist/components/NotificationCenter/NotificationCenter.js +83 -0
- package/dist/components/NotificationCenter/NotificationCenter.js.map +1 -0
- package/dist/components/NotificationCenter/NotificationCenter.module.cjs +2 -0
- package/dist/components/NotificationCenter/NotificationCenter.module.cjs.map +1 -0
- package/dist/components/NotificationCenter/NotificationCenter.module.js +21 -0
- package/dist/components/NotificationCenter/NotificationCenter.module.js.map +1 -0
- package/dist/components/NotificationCenter/use-notification-inbox.cjs +2 -0
- package/dist/components/NotificationCenter/use-notification-inbox.cjs.map +1 -0
- package/dist/components/NotificationCenter/use-notification-inbox.js +63 -0
- package/dist/components/NotificationCenter/use-notification-inbox.js.map +1 -0
- package/dist/components/RefreshIndicator/RefreshIndicator.cjs +1 -1
- package/dist/components/RefreshIndicator/RefreshIndicator.cjs.map +1 -1
- package/dist/components/RefreshIndicator/RefreshIndicator.js +17 -17
- package/dist/components/RefreshIndicator/RefreshIndicator.js.map +1 -1
- package/dist/components/SignaturePad/SignaturePad.cjs +2 -0
- package/dist/components/SignaturePad/SignaturePad.cjs.map +1 -0
- package/dist/components/SignaturePad/SignaturePad.js +115 -0
- package/dist/components/SignaturePad/SignaturePad.js.map +1 -0
- package/dist/components/SignaturePad/SignaturePad.module.cjs +2 -0
- package/dist/components/SignaturePad/SignaturePad.module.cjs.map +1 -0
- package/dist/components/SignaturePad/SignaturePad.module.js +11 -0
- package/dist/components/SignaturePad/SignaturePad.module.js.map +1 -0
- package/dist/components/Stepper/Stepper.cjs +1 -1
- package/dist/components/Stepper/Stepper.cjs.map +1 -1
- package/dist/components/Stepper/Stepper.js +43 -19
- package/dist/components/Stepper/Stepper.js.map +1 -1
- package/dist/components/Stepper/Stepper.module.cjs +1 -1
- package/dist/components/Stepper/Stepper.module.cjs.map +1 -1
- package/dist/components/Stepper/Stepper.module.js +6 -3
- package/dist/components/Stepper/Stepper.module.js.map +1 -1
- package/dist/components/Tooltip/Tooltip.cjs +1 -1
- package/dist/components/Tooltip/Tooltip.cjs.map +1 -1
- package/dist/components/Tooltip/Tooltip.js +26 -20
- package/dist/components/Tooltip/Tooltip.js.map +1 -1
- package/dist/components/TreeView/TreeView.cjs +2 -0
- package/dist/components/TreeView/TreeView.cjs.map +1 -0
- package/dist/components/TreeView/TreeView.js +124 -0
- package/dist/components/TreeView/TreeView.js.map +1 -0
- package/dist/components/TreeView/TreeView.module.cjs +2 -0
- package/dist/components/TreeView/TreeView.module.cjs.map +1 -0
- package/dist/components/TreeView/TreeView.module.js +17 -0
- package/dist/components/TreeView/TreeView.module.js.map +1 -0
- package/dist/components/VirtualTable/VirtualTable.cjs +2 -0
- package/dist/components/VirtualTable/VirtualTable.cjs.map +1 -0
- package/dist/components/VirtualTable/VirtualTable.js +116 -0
- package/dist/components/VirtualTable/VirtualTable.js.map +1 -0
- package/dist/components/VirtualTable/VirtualTable.module.cjs +2 -0
- package/dist/components/VirtualTable/VirtualTable.module.cjs.map +1 -0
- package/dist/components/VirtualTable/VirtualTable.module.js +20 -0
- package/dist/components/VirtualTable/VirtualTable.module.js.map +1 -0
- package/dist/components/Wizard/Wizard.cjs +2 -0
- package/dist/components/Wizard/Wizard.cjs.map +1 -0
- package/dist/components/Wizard/Wizard.js +111 -0
- package/dist/components/Wizard/Wizard.js.map +1 -0
- package/dist/components/Wizard/Wizard.module.cjs +2 -0
- package/dist/components/Wizard/Wizard.module.cjs.map +1 -0
- package/dist/components/Wizard/Wizard.module.js +10 -0
- package/dist/components/Wizard/Wizard.module.js.map +1 -0
- package/dist/geo/use-position-tracker.cjs +1 -1
- package/dist/geo/use-position-tracker.cjs.map +1 -1
- package/dist/geo/use-position-tracker.js +3 -1
- package/dist/geo/use-position-tracker.js.map +1 -1
- package/dist/hooks/use-async.cjs +1 -1
- package/dist/hooks/use-async.cjs.map +1 -1
- package/dist/hooks/use-async.js +3 -1
- package/dist/hooks/use-async.js.map +1 -1
- package/dist/hooks/use-click-outside.cjs +1 -1
- package/dist/hooks/use-click-outside.cjs.map +1 -1
- package/dist/hooks/use-click-outside.js +3 -1
- package/dist/hooks/use-click-outside.js.map +1 -1
- package/dist/hooks/use-deep-memo.cjs.map +1 -1
- package/dist/hooks/use-deep-memo.js.map +1 -1
- package/dist/hooks/use-event-listener.cjs +1 -1
- package/dist/hooks/use-event-listener.cjs.map +1 -1
- package/dist/hooks/use-event-listener.js +3 -1
- package/dist/hooks/use-event-listener.js.map +1 -1
- package/dist/hooks/use-interval.cjs +1 -1
- package/dist/hooks/use-interval.cjs.map +1 -1
- package/dist/hooks/use-interval.js +3 -1
- package/dist/hooks/use-interval.js.map +1 -1
- package/dist/hooks/use-is-first-render.cjs.map +1 -1
- package/dist/hooks/use-is-first-render.js.map +1 -1
- package/dist/hooks/use-long-press-handlers.cjs +1 -1
- package/dist/hooks/use-long-press-handlers.cjs.map +1 -1
- package/dist/hooks/use-long-press-handlers.js +25 -23
- package/dist/hooks/use-long-press-handlers.js.map +1 -1
- package/dist/hooks/use-long-press.cjs +1 -1
- package/dist/hooks/use-long-press.cjs.map +1 -1
- package/dist/hooks/use-long-press.js +3 -1
- package/dist/hooks/use-long-press.js.map +1 -1
- package/dist/hooks/use-online.cjs +1 -1
- package/dist/hooks/use-online.cjs.map +1 -1
- package/dist/hooks/use-online.js +6 -4
- package/dist/hooks/use-online.js.map +1 -1
- package/dist/hooks/use-previous.cjs.map +1 -1
- package/dist/hooks/use-previous.js.map +1 -1
- package/dist/hooks/use-service-worker-update.cjs +1 -1
- package/dist/hooks/use-service-worker-update.cjs.map +1 -1
- package/dist/hooks/use-service-worker-update.js +3 -1
- package/dist/hooks/use-service-worker-update.js.map +1 -1
- package/dist/hooks/use-sortable.cjs +2 -0
- package/dist/hooks/use-sortable.cjs.map +1 -0
- package/dist/hooks/use-sortable.js +169 -0
- package/dist/hooks/use-sortable.js.map +1 -0
- package/dist/hooks/use-stable-callback.cjs.map +1 -1
- package/dist/hooks/use-stable-callback.js.map +1 -1
- package/dist/hooks/use-timeout.cjs +1 -1
- package/dist/hooks/use-timeout.cjs.map +1 -1
- package/dist/hooks/use-timeout.js +3 -1
- package/dist/hooks/use-timeout.js.map +1 -1
- package/dist/icons/Icon.cjs +2 -0
- package/dist/icons/Icon.cjs.map +1 -0
- package/dist/icons/Icon.js +24 -0
- package/dist/icons/Icon.js.map +1 -0
- package/dist/icons/IconProvider.cjs +2 -0
- package/dist/icons/IconProvider.cjs.map +1 -0
- package/dist/icons/IconProvider.js +24 -0
- package/dist/icons/IconProvider.js.map +1 -0
- package/dist/icons/generated/aliases.cjs +2 -0
- package/dist/icons/generated/aliases.cjs.map +1 -0
- package/dist/icons/generated/aliases.js +255 -0
- package/dist/icons/generated/aliases.js.map +1 -0
- package/dist/icons/generated/icon-names.cjs +2 -0
- package/dist/icons/generated/icon-names.cjs.map +1 -0
- package/dist/icons/generated/icon-names.js +6 -0
- package/dist/icons/generated/icon-names.js.map +1 -0
- package/dist/icons/generated/loaders.cjs +2 -0
- package/dist/icons/generated/loaders.cjs.map +1 -0
- package/dist/icons/generated/loaders.js +32 -0
- package/dist/icons/generated/loaders.js.map +1 -0
- package/dist/icons/generated/shard-a.cjs +2 -0
- package/dist/icons/generated/shard-a.cjs.map +1 -0
- package/dist/icons/generated/shard-a.js +114 -0
- package/dist/icons/generated/shard-a.js.map +1 -0
- package/dist/icons/generated/shard-b.cjs +2 -0
- package/dist/icons/generated/shard-b.cjs.map +1 -0
- package/dist/icons/generated/shard-b.js +156 -0
- package/dist/icons/generated/shard-b.js.map +1 -0
- package/dist/icons/generated/shard-c.cjs +2 -0
- package/dist/icons/generated/shard-c.cjs.map +1 -0
- package/dist/icons/generated/shard-c.js +269 -0
- package/dist/icons/generated/shard-c.js.map +1 -0
- package/dist/icons/generated/shard-d.cjs +2 -0
- package/dist/icons/generated/shard-d.cjs.map +1 -0
- package/dist/icons/generated/shard-d.js +62 -0
- package/dist/icons/generated/shard-d.js.map +1 -0
- package/dist/icons/generated/shard-e.cjs +2 -0
- package/dist/icons/generated/shard-e.cjs.map +1 -0
- package/dist/icons/generated/shard-e.js +32 -0
- package/dist/icons/generated/shard-e.js.map +1 -0
- package/dist/icons/generated/shard-f.cjs +2 -0
- package/dist/icons/generated/shard-f.cjs.map +1 -0
- package/dist/icons/generated/shard-f.js +139 -0
- package/dist/icons/generated/shard-f.js.map +1 -0
- package/dist/icons/generated/shard-g.cjs +2 -0
- package/dist/icons/generated/shard-g.cjs.map +1 -0
- package/dist/icons/generated/shard-g.js +61 -0
- package/dist/icons/generated/shard-g.js.map +1 -0
- package/dist/icons/generated/shard-h.cjs +2 -0
- package/dist/icons/generated/shard-h.cjs.map +1 -0
- package/dist/icons/generated/shard-h.js +63 -0
- package/dist/icons/generated/shard-h.js.map +1 -0
- package/dist/icons/generated/shard-i.cjs +2 -0
- package/dist/icons/generated/shard-i.cjs.map +1 -0
- package/dist/icons/generated/shard-i.js +30 -0
- package/dist/icons/generated/shard-i.js.map +1 -0
- package/dist/icons/generated/shard-j.cjs +2 -0
- package/dist/icons/generated/shard-j.cjs.map +1 -0
- package/dist/icons/generated/shard-j.js +10 -0
- package/dist/icons/generated/shard-j.js.map +1 -0
- package/dist/icons/generated/shard-k.cjs +2 -0
- package/dist/icons/generated/shard-k.cjs.map +1 -0
- package/dist/icons/generated/shard-k.js +16 -0
- package/dist/icons/generated/shard-k.js.map +1 -0
- package/dist/icons/generated/shard-l.cjs +2 -0
- package/dist/icons/generated/shard-l.cjs.map +1 -0
- package/dist/icons/generated/shard-l.js +88 -0
- package/dist/icons/generated/shard-l.js.map +1 -0
- package/dist/icons/generated/shard-m.cjs +2 -0
- package/dist/icons/generated/shard-m.cjs.map +1 -0
- package/dist/icons/generated/shard-m.js +140 -0
- package/dist/icons/generated/shard-m.js.map +1 -0
- package/dist/icons/generated/shard-n.cjs +2 -0
- package/dist/icons/generated/shard-n.cjs.map +1 -0
- package/dist/icons/generated/shard-n.js +24 -0
- package/dist/icons/generated/shard-n.js.map +1 -0
- package/dist/icons/generated/shard-o.cjs +2 -0
- package/dist/icons/generated/shard-o.cjs.map +1 -0
- package/dist/icons/generated/shard-o.js +17 -0
- package/dist/icons/generated/shard-o.js.map +1 -0
- package/dist/icons/generated/shard-p.cjs +2 -0
- package/dist/icons/generated/shard-p.cjs.map +1 -0
- package/dist/icons/generated/shard-p.js +115 -0
- package/dist/icons/generated/shard-p.js.map +1 -0
- package/dist/icons/generated/shard-q.cjs +2 -0
- package/dist/icons/generated/shard-q.cjs.map +1 -0
- package/dist/icons/generated/shard-q.js +10 -0
- package/dist/icons/generated/shard-q.js.map +1 -0
- package/dist/icons/generated/shard-r.cjs +2 -0
- package/dist/icons/generated/shard-r.cjs.map +1 -0
- package/dist/icons/generated/shard-r.js +77 -0
- package/dist/icons/generated/shard-r.js.map +1 -0
- package/dist/icons/generated/shard-s.cjs +2 -0
- package/dist/icons/generated/shard-s.cjs.map +1 -0
- package/dist/icons/generated/shard-s.js +255 -0
- package/dist/icons/generated/shard-s.js.map +1 -0
- package/dist/icons/generated/shard-t.cjs +2 -0
- package/dist/icons/generated/shard-t.cjs.map +1 -0
- package/dist/icons/generated/shard-t.js +109 -0
- package/dist/icons/generated/shard-t.js.map +1 -0
- package/dist/icons/generated/shard-u.cjs +2 -0
- package/dist/icons/generated/shard-u.cjs.map +1 -0
- package/dist/icons/generated/shard-u.js +49 -0
- package/dist/icons/generated/shard-u.js.map +1 -0
- package/dist/icons/generated/shard-v.cjs +2 -0
- package/dist/icons/generated/shard-v.cjs.map +1 -0
- package/dist/icons/generated/shard-v.js +30 -0
- package/dist/icons/generated/shard-v.js.map +1 -0
- package/dist/icons/generated/shard-w.cjs +2 -0
- package/dist/icons/generated/shard-w.cjs.map +1 -0
- package/dist/icons/generated/shard-w.js +48 -0
- package/dist/icons/generated/shard-w.js.map +1 -0
- package/dist/icons/generated/shard-x.cjs +2 -0
- package/dist/icons/generated/shard-x.cjs.map +1 -0
- package/dist/icons/generated/shard-x.js +10 -0
- package/dist/icons/generated/shard-x.js.map +1 -0
- package/dist/icons/generated/shard-z.cjs +2 -0
- package/dist/icons/generated/shard-z.cjs.map +1 -0
- package/dist/icons/generated/shard-z.js +25 -0
- package/dist/icons/generated/shard-z.js.map +1 -0
- package/dist/icons/icon-context.cjs +2 -0
- package/dist/icons/icon-context.cjs.map +1 -0
- package/dist/icons/icon-context.js +13 -0
- package/dist/icons/icon-context.js.map +1 -0
- package/dist/icons/is-icon-name.cjs +2 -0
- package/dist/icons/is-icon-name.cjs.map +1 -0
- package/dist/icons/is-icon-name.js +10 -0
- package/dist/icons/is-icon-name.js.map +1 -0
- package/dist/icons/shard-cache.cjs +2 -0
- package/dist/icons/shard-cache.cjs.map +1 -0
- package/dist/icons/shard-cache.js +41 -0
- package/dist/icons/shard-cache.js.map +1 -0
- package/dist/icons/use-icon.cjs +2 -0
- package/dist/icons/use-icon.cjs.map +1 -0
- package/dist/icons/use-icon.js +20 -0
- package/dist/icons/use-icon.js.map +1 -0
- package/dist/icons-virtual.d.ts +22 -0
- package/dist/icons.cjs +1 -0
- package/dist/icons.d.ts +220 -0
- package/dist/icons.js +9 -0
- package/dist/offline/create-offline-sync.cjs +1 -1
- package/dist/offline/create-offline-sync.cjs.map +1 -1
- package/dist/offline/create-offline-sync.js +8 -2
- package/dist/offline/create-offline-sync.js.map +1 -1
- package/dist/offline/use-offline-sync.cjs +1 -1
- package/dist/offline/use-offline-sync.cjs.map +1 -1
- package/dist/offline/use-offline-sync.js +3 -1
- package/dist/offline/use-offline-sync.js.map +1 -1
- package/dist/push/use-push-subscription.cjs +1 -1
- package/dist/push/use-push-subscription.cjs.map +1 -1
- package/dist/push/use-push-subscription.js +3 -1
- package/dist/push/use-push-subscription.js.map +1 -1
- package/dist/sse/use-event-stream.cjs +1 -1
- package/dist/sse/use-event-stream.cjs.map +1 -1
- package/dist/sse/use-event-stream.js +3 -1
- package/dist/sse/use-event-stream.js.map +1 -1
- package/dist/styles.css +1 -1
- package/dist/tempest-react-sdk.cjs +1 -1
- package/dist/tempest-react-sdk.d.ts +1187 -2
- package/dist/tempest-react-sdk.js +261 -246
- package/dist/theme/ThemeProvider.cjs +1 -1
- package/dist/theme/ThemeProvider.cjs.map +1 -1
- package/dist/theme/ThemeProvider.js +6 -2
- package/dist/theme/ThemeProvider.js.map +1 -1
- package/dist/theme/apply-theme.cjs +2 -0
- package/dist/theme/apply-theme.cjs.map +1 -0
- package/dist/theme/apply-theme.js +24 -0
- package/dist/theme/apply-theme.js.map +1 -0
- package/dist/theme/color.cjs +2 -0
- package/dist/theme/color.cjs.map +1 -0
- package/dist/theme/color.js +161 -0
- package/dist/theme/color.js.map +1 -0
- package/dist/theme/create-theme.cjs +5 -0
- package/dist/theme/create-theme.cjs.map +1 -0
- package/dist/theme/create-theme.js +141 -0
- package/dist/theme/create-theme.js.map +1 -0
- package/dist/theme/theme-presets.cjs +2 -0
- package/dist/theme/theme-presets.cjs.map +1 -0
- package/dist/theme/theme-presets.js +82 -0
- package/dist/theme/theme-presets.js.map +1 -0
- package/dist/utilities.css +432 -0
- package/dist/utils/compare-values.cjs +2 -0
- package/dist/utils/compare-values.cjs.map +1 -0
- package/dist/utils/compare-values.js +8 -0
- package/dist/utils/compare-values.js.map +1 -0
- package/dist/vision/use-camera-stream.cjs +1 -1
- package/dist/vision/use-camera-stream.cjs.map +1 -1
- package/dist/vision/use-camera-stream.js +3 -1
- package/dist/vision/use-camera-stream.js.map +1 -1
- package/dist/vite/create-vite-config.cjs +1 -1
- package/dist/vite/create-vite-config.cjs.map +1 -1
- package/dist/vite/create-vite-config.js +30 -22
- package/dist/vite/create-vite-config.js.map +1 -1
- package/dist/vite/tempest-icons.cjs +9 -0
- package/dist/vite/tempest-icons.cjs.map +1 -0
- package/dist/vite/tempest-icons.js +99 -0
- package/dist/vite/tempest-icons.js.map +1 -0
- package/dist/vite.cjs +1 -1
- package/dist/vite.d.ts +79 -0
- package/dist/vite.js +6 -5
- package/dist/ws/use-web-socket.cjs +1 -1
- package/dist/ws/use-web-socket.cjs.map +1 -1
- package/dist/ws/use-web-socket.js +3 -1
- package/dist/ws/use-web-socket.js.map +1 -1
- package/package.json +14 -4
- package/template/package.json +1 -1
|
@@ -1,34 +1,40 @@
|
|
|
1
1
|
import { cn as e } from "../../utils/cn.js";
|
|
2
2
|
import t from "./Tooltip.module.js";
|
|
3
|
-
import { cloneElement as n,
|
|
4
|
-
import { jsx as
|
|
3
|
+
import { cloneElement as n, useEffect as r, useId as i, useRef as a, useState as o } from "react";
|
|
4
|
+
import { jsx as s, jsxs as c } from "react/jsx-runtime";
|
|
5
5
|
//#region src/components/Tooltip/Tooltip.tsx
|
|
6
|
-
function
|
|
7
|
-
let [
|
|
8
|
-
function
|
|
9
|
-
|
|
6
|
+
function l({ content: l, placement: u = "top", children: d, disabled: f = !1, openDelay: p = 150 }) {
|
|
7
|
+
let [m, h] = o(!1), g = i(), _ = a(null);
|
|
8
|
+
function v() {
|
|
9
|
+
_.current !== null && (clearTimeout(_.current), _.current = null);
|
|
10
10
|
}
|
|
11
|
-
function
|
|
12
|
-
|
|
11
|
+
function y() {
|
|
12
|
+
f || (v(), _.current = setTimeout(() => h(!0), p));
|
|
13
13
|
}
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
14
|
+
function b() {
|
|
15
|
+
v(), h(!1);
|
|
16
|
+
}
|
|
17
|
+
r(() => () => {
|
|
18
|
+
v();
|
|
19
|
+
}, []);
|
|
20
|
+
let x = n(d, {
|
|
21
|
+
onMouseEnter: y,
|
|
22
|
+
onMouseLeave: b,
|
|
23
|
+
onFocus: y,
|
|
24
|
+
onBlur: b,
|
|
25
|
+
"aria-describedby": m ? g : void 0
|
|
20
26
|
});
|
|
21
|
-
return /* @__PURE__ */
|
|
27
|
+
return /* @__PURE__ */ c("span", {
|
|
22
28
|
className: t.trigger,
|
|
23
|
-
children: [
|
|
24
|
-
id:
|
|
29
|
+
children: [x, m && /* @__PURE__ */ s("span", {
|
|
30
|
+
id: g,
|
|
25
31
|
role: "tooltip",
|
|
26
|
-
className: e(t.bubble, t[
|
|
27
|
-
children:
|
|
32
|
+
className: e(t.bubble, t[u]),
|
|
33
|
+
children: l
|
|
28
34
|
})]
|
|
29
35
|
});
|
|
30
36
|
}
|
|
31
37
|
//#endregion
|
|
32
|
-
export {
|
|
38
|
+
export { l as Tooltip };
|
|
33
39
|
|
|
34
40
|
//# sourceMappingURL=Tooltip.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Tooltip.js","names":[],"sources":["../../../src/components/Tooltip/Tooltip.tsx"],"sourcesContent":["
|
|
1
|
+
{"version":3,"file":"Tooltip.js","names":[],"sources":["../../../src/components/Tooltip/Tooltip.tsx"],"sourcesContent":["/* eslint-disable react-hooks/refs -- the handlers below read the timer ref, and they only\n run on user events (hover/focus), never during render */\nimport { cloneElement, useEffect, useId, useRef, useState } from \"react\";\nimport type { ReactElement, ReactNode } from \"react\";\nimport { cn } from \"@/utils/cn\";\nimport styles from \"./Tooltip.module.css\";\n\nexport type TooltipPlacement = \"top\" | \"bottom\" | \"left\" | \"right\";\n\nexport interface TooltipProps {\n /** Tooltip content. Plain text recommended; rich content also works. */\n content: ReactNode;\n /** Placement relative to the trigger. Default: `\"top\"`. */\n placement?: TooltipPlacement;\n /** Single React element to attach hover/focus listeners to. */\n children: ReactElement;\n /** Disable the tooltip without changing the trigger. */\n disabled?: boolean;\n /** Delay (ms) before showing the tooltip. Default: 150. */\n openDelay?: number;\n}\n\n/**\n * Lightweight tooltip. Shows on hover and on focus (keyboard-friendly). Wraps\n * a single child element via `cloneElement`, so the trigger keeps its own ref\n * and props.\n */\nexport function Tooltip({\n content,\n placement = \"top\",\n children,\n disabled = false,\n openDelay = 150,\n}: TooltipProps) {\n const [open, setOpen] = useState<boolean>(false);\n const tooltipId = useId();\n /**\n * Handle of the pending open timer.\n *\n * A ref, not a `let` in the component body: that binding is recreated on every\n * render, so any re-render between `show` and `hide` (a parent update, a state\n * change elsewhere) dropped the handle and `clearTimeout` silently cancelled\n * nothing — the tooltip then opened after the pointer had already left.\n */\n const timerRef = useRef<ReturnType<typeof setTimeout> | null>(null);\n\n function clearTimer(): void {\n if (timerRef.current !== null) {\n clearTimeout(timerRef.current);\n timerRef.current = null;\n }\n }\n\n function show(): void {\n if (disabled) return;\n clearTimer();\n timerRef.current = setTimeout(() => setOpen(true), openDelay);\n }\n\n function hide(): void {\n clearTimer();\n setOpen(false);\n }\n\n useEffect(() => {\n return () => {\n clearTimer();\n };\n }, []);\n\n const trigger = cloneElement(children, {\n onMouseEnter: show,\n onMouseLeave: hide,\n onFocus: show,\n onBlur: hide,\n \"aria-describedby\": open ? tooltipId : undefined,\n } as Record<string, unknown>);\n\n return (\n <span className={styles.trigger}>\n {trigger}\n {open && (\n <span\n id={tooltipId}\n role=\"tooltip\"\n className={cn(styles.bubble, styles[placement])}\n >\n {content}\n </span>\n )}\n </span>\n );\n}\n"],"mappings":";;;;;AA2BA,SAAgB,EAAQ,EACpB,YACA,eAAY,OACZ,aACA,cAAW,IACX,eAAY,OACC;CACb,IAAM,CAAC,GAAM,KAAW,EAAkB,EAAK,GACzC,IAAY,EAAM,GASlB,IAAW,EAA6C,IAAI;CAElE,SAAS,IAAmB;EACxB,AAAI,EAAS,YAAY,SACrB,aAAa,EAAS,OAAO,GAC7B,EAAS,UAAU;CAE3B;CAEA,SAAS,IAAa;EACd,MACJ,EAAW,GACX,EAAS,UAAU,iBAAiB,EAAQ,EAAI,GAAG,CAAS;CAChE;CAEA,SAAS,IAAa;EAElB,AADA,EAAW,GACX,EAAQ,EAAK;CACjB;CAEA,cACiB;EACT,EAAW;CACf,GACD,CAAC,CAAC;CAEL,IAAM,IAAU,EAAa,GAAU;EACnC,cAAc;EACd,cAAc;EACd,SAAS;EACT,QAAQ;EACR,oBAAoB,IAAO,IAAY,KAAA;CAC3C,CAA4B;CAE5B,OACI,kBAAC,QAAD;EAAM,WAAW,EAAO;YAAxB,CACK,GACA,KACG,kBAAC,QAAD;GACI,IAAI;GACJ,MAAK;GACL,WAAW,EAAG,EAAO,QAAQ,EAAO,EAAU;aAE7C;EACC,CAAA,CAER;;AAEd"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
const e=require("../../utils/cn.cjs"),t=require("./TreeView.module.cjs");let n=require("react"),r=require("react/jsx-runtime"),i=require("lucide-react");function a(e,t,n=0,r=null,i=[]){for(let o of e){let e=Array.isArray(o.children),s=e&&t.has(o.id);i.push({node:o,depth:n,parentId:r,hasChildren:e,expanded:s}),s&&o.children&&a(o.children,t,n+1,o.id,i)}return i}function o({nodes:o,expandedIds:s,defaultExpandedIds:c=[],onExpandedChange:l,selectedId:u,defaultSelectedId:d=null,onSelect:f,toggleOnSelect:p=!0,label:m,className:h}){let g=s!==void 0,[_,v]=(0,n.useState)(c),y=g?s:_,b=u!==void 0,[x,S]=(0,n.useState)(d),C=b?u:x,w=(0,n.useMemo)(()=>new Set(y),[y]),T=(0,n.useMemo)(()=>a(o,w),[o,w]),[E,D]=(0,n.useState)(null),O=(0,n.useRef)(null),k=E??C??T.find(e=>!e.node.disabled)?.node.id??null,A=(0,n.useCallback)(e=>{g||v(e),l?.(e)},[g,l]),j=(0,n.useCallback)(e=>{A(y.includes(e)?y.filter(t=>t!==e):[...y,e])},[y,A]),M=(0,n.useCallback)(e=>{e.node.disabled||(b||S(e.node.id),D(e.node.id),f?.(e.node),e.hasChildren&&p&&j(e.node.id))},[f,b,j,p]),N=(0,n.useCallback)(e=>{D(e),(O.current?.querySelector(`[data-tree-id="${e}"]`))?.focus()},[]),P=(0,n.useCallback)((e,t)=>{for(let n=e+t;n>=0&&n<T.length;n+=t)if(!T[n].node.disabled){N(T[n].node.id);return}},[T,N]),F=(0,n.useCallback)((e,t,n)=>{switch(e.key){case`ArrowDown`:e.preventDefault(),P(n,1);break;case`ArrowUp`:e.preventDefault(),P(n,-1);break;case`ArrowRight`:e.preventDefault(),t.hasChildren&&!t.expanded?j(t.node.id):t.expanded&&P(n,1);break;case`ArrowLeft`:e.preventDefault(),t.expanded?j(t.node.id):t.parentId&&N(t.parentId);break;case`Home`:e.preventDefault(),P(-1,1);break;case`End`:e.preventDefault(),P(T.length,-1);break;case`Enter`:case` `:e.preventDefault(),M(t);break;default:break}},[P,T.length,M,j,N]);return(0,r.jsx)(`ul`,{ref:O,role:`tree`,"aria-label":m,className:e.cn(t.default.tree,h),children:T.map((n,a)=>{let o=C===n.node.id;return(0,r.jsx)(`li`,{role:`treeitem`,"aria-expanded":n.hasChildren?n.expanded:void 0,"aria-selected":o,"aria-level":n.depth+1,"aria-disabled":n.node.disabled||void 0,className:t.default.item,children:(0,r.jsxs)(`div`,{"data-tree-id":n.node.id,className:e.cn(t.default.row,o&&t.default.selected,n.node.disabled&&t.default.disabled),style:{paddingInlineStart:`calc(${n.depth} * var(--tempest-space-5))`},tabIndex:k===n.node.id&&!n.node.disabled?0:-1,onClick:()=>M(n),onFocus:()=>D(n.node.id),onKeyDown:e=>F(e,n,a),children:[n.hasChildren?(0,r.jsx)(`span`,{className:e.cn(t.default.chevron,n.expanded&&t.default.chevronOpen),"aria-hidden":`true`,onClick:e=>{e.stopPropagation(),n.node.disabled||j(n.node.id)},children:(0,r.jsx)(i.ChevronRight,{size:14})}):(0,r.jsx)(`span`,{className:t.default.chevronPlaceholder,"aria-hidden":`true`}),n.node.icon?(0,r.jsx)(`span`,{className:t.default.icon,"aria-hidden":`true`,children:n.node.icon}):null,(0,r.jsx)(`span`,{className:t.default.label,children:n.node.label})]})},n.node.id)})})}exports.TreeView=o;
|
|
2
|
+
//# sourceMappingURL=TreeView.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"TreeView.cjs","names":[],"sources":["../../../src/components/TreeView/TreeView.tsx"],"sourcesContent":["import { ChevronRight } from \"lucide-react\";\nimport { useCallback, useMemo, useRef, useState } from \"react\";\nimport type { KeyboardEvent, ReactNode } from \"react\";\nimport { cn } from \"@/utils/cn\";\nimport styles from \"./TreeView.module.css\";\n\n/** One node of the tree. Children make it a branch; no children makes it a leaf. */\nexport interface TreeNode {\n /** Stable identifier, unique across the whole tree. */\n id: string;\n /** Rendered label. */\n label: ReactNode;\n /** Child nodes. An empty array still renders as a branch (an empty folder). */\n children?: TreeNode[];\n /** Icon rendered before the label. */\n icon?: ReactNode;\n /** Blocks selection and expansion, and skips the node in keyboard navigation. */\n disabled?: boolean;\n}\n\nexport interface TreeViewProps {\n /** Root nodes. */\n nodes: TreeNode[];\n /** Controlled expanded ids. */\n expandedIds?: string[];\n /** Uncontrolled initial expanded ids. */\n defaultExpandedIds?: string[];\n onExpandedChange?: (expandedIds: string[]) => void;\n /** Controlled selected id. `null` means nothing selected. */\n selectedId?: string | null;\n /** Uncontrolled initial selection. */\n defaultSelectedId?: string | null;\n onSelect?: (node: TreeNode) => void;\n /**\n * Selecting a branch also toggles it. Default `true` — matches how a file\n * explorer behaves; set `false` when a branch is itself a meaningful choice\n * (a category that owns items, for instance).\n */\n toggleOnSelect?: boolean;\n /** Accessible name for the tree. */\n label?: string;\n className?: string;\n}\n\ninterface FlatNode {\n node: TreeNode;\n depth: number;\n parentId: string | null;\n hasChildren: boolean;\n expanded: boolean;\n}\n\n/**\n * Walk the tree into the list of *currently visible* rows.\n *\n * Keyboard navigation works on this flattened view, which is what makes\n * ArrowDown from the last child of a collapsed-sibling branch land on the right\n * row: rows that are not rendered simply are not in the list.\n */\nfunction flatten(\n nodes: TreeNode[],\n expandedIds: Set<string>,\n depth = 0,\n parentId: string | null = null,\n out: FlatNode[] = [],\n): FlatNode[] {\n for (const node of nodes) {\n const hasChildren = Array.isArray(node.children);\n const expanded = hasChildren && expandedIds.has(node.id);\n out.push({ node, depth, parentId, hasChildren, expanded });\n if (expanded && node.children) {\n flatten(node.children, expandedIds, depth + 1, node.id, out);\n }\n }\n return out;\n}\n\n/**\n * Accessible tree for hierarchical data — categories, permissions, folders, an\n * org chart.\n *\n * Implements the `tree` role with **roving tabindex**: exactly one row is\n * tabbable, and the arrow keys move focus within the widget. That is what keeps a\n * 500-node tree from adding 500 stops to the page's tab order.\n *\n * Keyboard map: `↓`/`↑` move, `→` expands (or descends), `←` collapses (or goes to\n * the parent), `Home`/`End` jump to the first/last visible row, `Enter`/`Space`\n * select.\n *\n * The chevron is decoration (`aria-hidden`), not a button: the row itself carries\n * `aria-expanded`, so a second focusable control there would only add noise for a\n * screen reader while duplicating an action the keyboard map already has. It still\n * accepts a click, with the event stopped so it toggles without also selecting.\n *\n * @example\n * ```tsx\n * const nodes: TreeNode[] = [\n * {\n * id: \"vendas\",\n * label: \"Vendas\",\n * children: [\n * { id: \"vendas.ler\", label: \"Ler\" },\n * { id: \"vendas.editar\", label: \"Editar\" },\n * ],\n * },\n * { id: \"config\", label: \"Configurações\", children: [] },\n * ];\n *\n * <TreeView nodes={nodes} defaultExpandedIds={[\"vendas\"]} onSelect={(node) => console.log(node.id)} />\n * ```\n */\nexport function TreeView({\n nodes,\n expandedIds,\n defaultExpandedIds = [],\n onExpandedChange,\n selectedId,\n defaultSelectedId = null,\n onSelect,\n toggleOnSelect = true,\n label,\n className,\n}: TreeViewProps) {\n const expandedControlled = expandedIds !== undefined;\n const [internalExpanded, setInternalExpanded] = useState<string[]>(defaultExpandedIds);\n const expanded = expandedControlled ? expandedIds : internalExpanded;\n\n const selectionControlled = selectedId !== undefined;\n const [internalSelected, setInternalSelected] = useState<string | null>(defaultSelectedId);\n const selected = selectionControlled ? selectedId : internalSelected;\n\n const expandedSet = useMemo(() => new Set(expanded), [expanded]);\n const rows = useMemo(() => flatten(nodes, expandedSet), [nodes, expandedSet]);\n\n const [focusedId, setFocusedId] = useState<string | null>(null);\n const containerRef = useRef<HTMLUListElement>(null);\n\n const activeId =\n focusedId ?? selected ?? rows.find((row) => !row.node.disabled)?.node.id ?? null;\n\n const setExpanded = useCallback(\n (next: string[]): void => {\n if (!expandedControlled) setInternalExpanded(next);\n onExpandedChange?.(next);\n },\n [expandedControlled, onExpandedChange],\n );\n\n const toggle = useCallback(\n (id: string): void => {\n setExpanded(\n expanded.includes(id) ? expanded.filter((x) => x !== id) : [...expanded, id],\n );\n },\n [expanded, setExpanded],\n );\n\n const select = useCallback(\n (row: FlatNode): void => {\n if (row.node.disabled) return;\n if (!selectionControlled) setInternalSelected(row.node.id);\n setFocusedId(row.node.id);\n onSelect?.(row.node);\n if (row.hasChildren && toggleOnSelect) toggle(row.node.id);\n },\n [onSelect, selectionControlled, toggle, toggleOnSelect],\n );\n\n /** Move DOM focus to a row by id, so the roving tabindex actually roves. */\n const focusRow = useCallback((id: string): void => {\n setFocusedId(id);\n const element = containerRef.current?.querySelector<HTMLElement>(`[data-tree-id=\"${id}\"]`);\n element?.focus();\n }, []);\n\n const moveFocus = useCallback(\n (from: number, delta: number): void => {\n for (let index = from + delta; index >= 0 && index < rows.length; index += delta) {\n if (!rows[index].node.disabled) {\n focusRow(rows[index].node.id);\n return;\n }\n }\n },\n [rows, focusRow],\n );\n\n const handleKeyDown = useCallback(\n (event: KeyboardEvent<HTMLDivElement>, row: FlatNode, index: number): void => {\n switch (event.key) {\n case \"ArrowDown\":\n event.preventDefault();\n moveFocus(index, 1);\n break;\n case \"ArrowUp\":\n event.preventDefault();\n moveFocus(index, -1);\n break;\n case \"ArrowRight\":\n event.preventDefault();\n if (row.hasChildren && !row.expanded) toggle(row.node.id);\n else if (row.expanded) moveFocus(index, 1);\n break;\n case \"ArrowLeft\":\n event.preventDefault();\n if (row.expanded) {\n toggle(row.node.id);\n } else if (row.parentId) {\n focusRow(row.parentId);\n }\n break;\n case \"Home\":\n event.preventDefault();\n moveFocus(-1, 1);\n break;\n case \"End\":\n event.preventDefault();\n moveFocus(rows.length, -1);\n break;\n case \"Enter\":\n case \" \":\n event.preventDefault();\n select(row);\n break;\n default:\n break;\n }\n },\n [moveFocus, rows.length, select, toggle, focusRow],\n );\n\n return (\n <ul\n ref={containerRef}\n role=\"tree\"\n aria-label={label}\n className={cn(styles.tree, className)}\n >\n {rows.map((row, index) => {\n const isSelected = selected === row.node.id;\n return (\n <li\n key={row.node.id}\n role=\"treeitem\"\n aria-expanded={row.hasChildren ? row.expanded : undefined}\n aria-selected={isSelected}\n aria-level={row.depth + 1}\n aria-disabled={row.node.disabled || undefined}\n className={styles.item}\n >\n <div\n data-tree-id={row.node.id}\n className={cn(\n styles.row,\n isSelected && styles.selected,\n row.node.disabled && styles.disabled,\n )}\n style={{\n paddingInlineStart: `calc(${row.depth} * var(--tempest-space-5))`,\n }}\n tabIndex={activeId === row.node.id && !row.node.disabled ? 0 : -1}\n onClick={() => select(row)}\n onFocus={() => setFocusedId(row.node.id)}\n onKeyDown={(event) => handleKeyDown(event, row, index)}\n >\n {row.hasChildren ? (\n <span\n className={cn(\n styles.chevron,\n row.expanded && styles.chevronOpen,\n )}\n aria-hidden=\"true\"\n onClick={(event) => {\n event.stopPropagation();\n if (!row.node.disabled) toggle(row.node.id);\n }}\n >\n <ChevronRight size={14} />\n </span>\n ) : (\n <span className={styles.chevronPlaceholder} aria-hidden=\"true\" />\n )}\n {row.node.icon ? (\n <span className={styles.icon} aria-hidden=\"true\">\n {row.node.icon}\n </span>\n ) : null}\n <span className={styles.label}>{row.node.label}</span>\n </div>\n </li>\n );\n })}\n </ul>\n );\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
import { cn as e } from "../../utils/cn.js";
|
|
2
|
+
import t from "./TreeView.module.js";
|
|
3
|
+
import { useCallback as n, useMemo as r, useRef as i, useState as a } from "react";
|
|
4
|
+
import { jsx as o, jsxs as s } from "react/jsx-runtime";
|
|
5
|
+
import { ChevronRight as c } from "lucide-react";
|
|
6
|
+
//#region src/components/TreeView/TreeView.tsx
|
|
7
|
+
function l(e, t, n = 0, r = null, i = []) {
|
|
8
|
+
for (let a of e) {
|
|
9
|
+
let e = Array.isArray(a.children), o = e && t.has(a.id);
|
|
10
|
+
i.push({
|
|
11
|
+
node: a,
|
|
12
|
+
depth: n,
|
|
13
|
+
parentId: r,
|
|
14
|
+
hasChildren: e,
|
|
15
|
+
expanded: o
|
|
16
|
+
}), o && a.children && l(a.children, t, n + 1, a.id, i);
|
|
17
|
+
}
|
|
18
|
+
return i;
|
|
19
|
+
}
|
|
20
|
+
function u({ nodes: u, expandedIds: d, defaultExpandedIds: f = [], onExpandedChange: p, selectedId: m, defaultSelectedId: h = null, onSelect: g, toggleOnSelect: _ = !0, label: v, className: y }) {
|
|
21
|
+
let b = d !== void 0, [x, S] = a(f), C = b ? d : x, w = m !== void 0, [T, E] = a(h), D = w ? m : T, O = r(() => new Set(C), [C]), k = r(() => l(u, O), [u, O]), [A, j] = a(null), M = i(null), N = A ?? D ?? k.find((e) => !e.node.disabled)?.node.id ?? null, P = n((e) => {
|
|
22
|
+
b || S(e), p?.(e);
|
|
23
|
+
}, [b, p]), F = n((e) => {
|
|
24
|
+
P(C.includes(e) ? C.filter((t) => t !== e) : [...C, e]);
|
|
25
|
+
}, [C, P]), I = n((e) => {
|
|
26
|
+
e.node.disabled || (w || E(e.node.id), j(e.node.id), g?.(e.node), e.hasChildren && _ && F(e.node.id));
|
|
27
|
+
}, [
|
|
28
|
+
g,
|
|
29
|
+
w,
|
|
30
|
+
F,
|
|
31
|
+
_
|
|
32
|
+
]), L = n((e) => {
|
|
33
|
+
j(e), (M.current?.querySelector(`[data-tree-id="${e}"]`))?.focus();
|
|
34
|
+
}, []), R = n((e, t) => {
|
|
35
|
+
for (let n = e + t; n >= 0 && n < k.length; n += t) if (!k[n].node.disabled) {
|
|
36
|
+
L(k[n].node.id);
|
|
37
|
+
return;
|
|
38
|
+
}
|
|
39
|
+
}, [k, L]), z = n((e, t, n) => {
|
|
40
|
+
switch (e.key) {
|
|
41
|
+
case "ArrowDown":
|
|
42
|
+
e.preventDefault(), R(n, 1);
|
|
43
|
+
break;
|
|
44
|
+
case "ArrowUp":
|
|
45
|
+
e.preventDefault(), R(n, -1);
|
|
46
|
+
break;
|
|
47
|
+
case "ArrowRight":
|
|
48
|
+
e.preventDefault(), t.hasChildren && !t.expanded ? F(t.node.id) : t.expanded && R(n, 1);
|
|
49
|
+
break;
|
|
50
|
+
case "ArrowLeft":
|
|
51
|
+
e.preventDefault(), t.expanded ? F(t.node.id) : t.parentId && L(t.parentId);
|
|
52
|
+
break;
|
|
53
|
+
case "Home":
|
|
54
|
+
e.preventDefault(), R(-1, 1);
|
|
55
|
+
break;
|
|
56
|
+
case "End":
|
|
57
|
+
e.preventDefault(), R(k.length, -1);
|
|
58
|
+
break;
|
|
59
|
+
case "Enter":
|
|
60
|
+
case " ":
|
|
61
|
+
e.preventDefault(), I(t);
|
|
62
|
+
break;
|
|
63
|
+
default: break;
|
|
64
|
+
}
|
|
65
|
+
}, [
|
|
66
|
+
R,
|
|
67
|
+
k.length,
|
|
68
|
+
I,
|
|
69
|
+
F,
|
|
70
|
+
L
|
|
71
|
+
]);
|
|
72
|
+
return /* @__PURE__ */ o("ul", {
|
|
73
|
+
ref: M,
|
|
74
|
+
role: "tree",
|
|
75
|
+
"aria-label": v,
|
|
76
|
+
className: e(t.tree, y),
|
|
77
|
+
children: k.map((n, r) => {
|
|
78
|
+
let i = D === n.node.id;
|
|
79
|
+
return /* @__PURE__ */ o("li", {
|
|
80
|
+
role: "treeitem",
|
|
81
|
+
"aria-expanded": n.hasChildren ? n.expanded : void 0,
|
|
82
|
+
"aria-selected": i,
|
|
83
|
+
"aria-level": n.depth + 1,
|
|
84
|
+
"aria-disabled": n.node.disabled || void 0,
|
|
85
|
+
className: t.item,
|
|
86
|
+
children: /* @__PURE__ */ s("div", {
|
|
87
|
+
"data-tree-id": n.node.id,
|
|
88
|
+
className: e(t.row, i && t.selected, n.node.disabled && t.disabled),
|
|
89
|
+
style: { paddingInlineStart: `calc(${n.depth} * var(--tempest-space-5))` },
|
|
90
|
+
tabIndex: N === n.node.id && !n.node.disabled ? 0 : -1,
|
|
91
|
+
onClick: () => I(n),
|
|
92
|
+
onFocus: () => j(n.node.id),
|
|
93
|
+
onKeyDown: (e) => z(e, n, r),
|
|
94
|
+
children: [
|
|
95
|
+
n.hasChildren ? /* @__PURE__ */ o("span", {
|
|
96
|
+
className: e(t.chevron, n.expanded && t.chevronOpen),
|
|
97
|
+
"aria-hidden": "true",
|
|
98
|
+
onClick: (e) => {
|
|
99
|
+
e.stopPropagation(), n.node.disabled || F(n.node.id);
|
|
100
|
+
},
|
|
101
|
+
children: /* @__PURE__ */ o(c, { size: 14 })
|
|
102
|
+
}) : /* @__PURE__ */ o("span", {
|
|
103
|
+
className: t.chevronPlaceholder,
|
|
104
|
+
"aria-hidden": "true"
|
|
105
|
+
}),
|
|
106
|
+
n.node.icon ? /* @__PURE__ */ o("span", {
|
|
107
|
+
className: t.icon,
|
|
108
|
+
"aria-hidden": "true",
|
|
109
|
+
children: n.node.icon
|
|
110
|
+
}) : null,
|
|
111
|
+
/* @__PURE__ */ o("span", {
|
|
112
|
+
className: t.label,
|
|
113
|
+
children: n.node.label
|
|
114
|
+
})
|
|
115
|
+
]
|
|
116
|
+
})
|
|
117
|
+
}, n.node.id);
|
|
118
|
+
})
|
|
119
|
+
});
|
|
120
|
+
}
|
|
121
|
+
//#endregion
|
|
122
|
+
export { u as TreeView };
|
|
123
|
+
|
|
124
|
+
//# sourceMappingURL=TreeView.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"TreeView.js","names":[],"sources":["../../../src/components/TreeView/TreeView.tsx"],"sourcesContent":["import { ChevronRight } from \"lucide-react\";\nimport { useCallback, useMemo, useRef, useState } from \"react\";\nimport type { KeyboardEvent, ReactNode } from \"react\";\nimport { cn } from \"@/utils/cn\";\nimport styles from \"./TreeView.module.css\";\n\n/** One node of the tree. Children make it a branch; no children makes it a leaf. */\nexport interface TreeNode {\n /** Stable identifier, unique across the whole tree. */\n id: string;\n /** Rendered label. */\n label: ReactNode;\n /** Child nodes. An empty array still renders as a branch (an empty folder). */\n children?: TreeNode[];\n /** Icon rendered before the label. */\n icon?: ReactNode;\n /** Blocks selection and expansion, and skips the node in keyboard navigation. */\n disabled?: boolean;\n}\n\nexport interface TreeViewProps {\n /** Root nodes. */\n nodes: TreeNode[];\n /** Controlled expanded ids. */\n expandedIds?: string[];\n /** Uncontrolled initial expanded ids. */\n defaultExpandedIds?: string[];\n onExpandedChange?: (expandedIds: string[]) => void;\n /** Controlled selected id. `null` means nothing selected. */\n selectedId?: string | null;\n /** Uncontrolled initial selection. */\n defaultSelectedId?: string | null;\n onSelect?: (node: TreeNode) => void;\n /**\n * Selecting a branch also toggles it. Default `true` — matches how a file\n * explorer behaves; set `false` when a branch is itself a meaningful choice\n * (a category that owns items, for instance).\n */\n toggleOnSelect?: boolean;\n /** Accessible name for the tree. */\n label?: string;\n className?: string;\n}\n\ninterface FlatNode {\n node: TreeNode;\n depth: number;\n parentId: string | null;\n hasChildren: boolean;\n expanded: boolean;\n}\n\n/**\n * Walk the tree into the list of *currently visible* rows.\n *\n * Keyboard navigation works on this flattened view, which is what makes\n * ArrowDown from the last child of a collapsed-sibling branch land on the right\n * row: rows that are not rendered simply are not in the list.\n */\nfunction flatten(\n nodes: TreeNode[],\n expandedIds: Set<string>,\n depth = 0,\n parentId: string | null = null,\n out: FlatNode[] = [],\n): FlatNode[] {\n for (const node of nodes) {\n const hasChildren = Array.isArray(node.children);\n const expanded = hasChildren && expandedIds.has(node.id);\n out.push({ node, depth, parentId, hasChildren, expanded });\n if (expanded && node.children) {\n flatten(node.children, expandedIds, depth + 1, node.id, out);\n }\n }\n return out;\n}\n\n/**\n * Accessible tree for hierarchical data — categories, permissions, folders, an\n * org chart.\n *\n * Implements the `tree` role with **roving tabindex**: exactly one row is\n * tabbable, and the arrow keys move focus within the widget. That is what keeps a\n * 500-node tree from adding 500 stops to the page's tab order.\n *\n * Keyboard map: `↓`/`↑` move, `→` expands (or descends), `←` collapses (or goes to\n * the parent), `Home`/`End` jump to the first/last visible row, `Enter`/`Space`\n * select.\n *\n * The chevron is decoration (`aria-hidden`), not a button: the row itself carries\n * `aria-expanded`, so a second focusable control there would only add noise for a\n * screen reader while duplicating an action the keyboard map already has. It still\n * accepts a click, with the event stopped so it toggles without also selecting.\n *\n * @example\n * ```tsx\n * const nodes: TreeNode[] = [\n * {\n * id: \"vendas\",\n * label: \"Vendas\",\n * children: [\n * { id: \"vendas.ler\", label: \"Ler\" },\n * { id: \"vendas.editar\", label: \"Editar\" },\n * ],\n * },\n * { id: \"config\", label: \"Configurações\", children: [] },\n * ];\n *\n * <TreeView nodes={nodes} defaultExpandedIds={[\"vendas\"]} onSelect={(node) => console.log(node.id)} />\n * ```\n */\nexport function TreeView({\n nodes,\n expandedIds,\n defaultExpandedIds = [],\n onExpandedChange,\n selectedId,\n defaultSelectedId = null,\n onSelect,\n toggleOnSelect = true,\n label,\n className,\n}: TreeViewProps) {\n const expandedControlled = expandedIds !== undefined;\n const [internalExpanded, setInternalExpanded] = useState<string[]>(defaultExpandedIds);\n const expanded = expandedControlled ? expandedIds : internalExpanded;\n\n const selectionControlled = selectedId !== undefined;\n const [internalSelected, setInternalSelected] = useState<string | null>(defaultSelectedId);\n const selected = selectionControlled ? selectedId : internalSelected;\n\n const expandedSet = useMemo(() => new Set(expanded), [expanded]);\n const rows = useMemo(() => flatten(nodes, expandedSet), [nodes, expandedSet]);\n\n const [focusedId, setFocusedId] = useState<string | null>(null);\n const containerRef = useRef<HTMLUListElement>(null);\n\n const activeId =\n focusedId ?? selected ?? rows.find((row) => !row.node.disabled)?.node.id ?? null;\n\n const setExpanded = useCallback(\n (next: string[]): void => {\n if (!expandedControlled) setInternalExpanded(next);\n onExpandedChange?.(next);\n },\n [expandedControlled, onExpandedChange],\n );\n\n const toggle = useCallback(\n (id: string): void => {\n setExpanded(\n expanded.includes(id) ? expanded.filter((x) => x !== id) : [...expanded, id],\n );\n },\n [expanded, setExpanded],\n );\n\n const select = useCallback(\n (row: FlatNode): void => {\n if (row.node.disabled) return;\n if (!selectionControlled) setInternalSelected(row.node.id);\n setFocusedId(row.node.id);\n onSelect?.(row.node);\n if (row.hasChildren && toggleOnSelect) toggle(row.node.id);\n },\n [onSelect, selectionControlled, toggle, toggleOnSelect],\n );\n\n /** Move DOM focus to a row by id, so the roving tabindex actually roves. */\n const focusRow = useCallback((id: string): void => {\n setFocusedId(id);\n const element = containerRef.current?.querySelector<HTMLElement>(`[data-tree-id=\"${id}\"]`);\n element?.focus();\n }, []);\n\n const moveFocus = useCallback(\n (from: number, delta: number): void => {\n for (let index = from + delta; index >= 0 && index < rows.length; index += delta) {\n if (!rows[index].node.disabled) {\n focusRow(rows[index].node.id);\n return;\n }\n }\n },\n [rows, focusRow],\n );\n\n const handleKeyDown = useCallback(\n (event: KeyboardEvent<HTMLDivElement>, row: FlatNode, index: number): void => {\n switch (event.key) {\n case \"ArrowDown\":\n event.preventDefault();\n moveFocus(index, 1);\n break;\n case \"ArrowUp\":\n event.preventDefault();\n moveFocus(index, -1);\n break;\n case \"ArrowRight\":\n event.preventDefault();\n if (row.hasChildren && !row.expanded) toggle(row.node.id);\n else if (row.expanded) moveFocus(index, 1);\n break;\n case \"ArrowLeft\":\n event.preventDefault();\n if (row.expanded) {\n toggle(row.node.id);\n } else if (row.parentId) {\n focusRow(row.parentId);\n }\n break;\n case \"Home\":\n event.preventDefault();\n moveFocus(-1, 1);\n break;\n case \"End\":\n event.preventDefault();\n moveFocus(rows.length, -1);\n break;\n case \"Enter\":\n case \" \":\n event.preventDefault();\n select(row);\n break;\n default:\n break;\n }\n },\n [moveFocus, rows.length, select, toggle, focusRow],\n );\n\n return (\n <ul\n ref={containerRef}\n role=\"tree\"\n aria-label={label}\n className={cn(styles.tree, className)}\n >\n {rows.map((row, index) => {\n const isSelected = selected === row.node.id;\n return (\n <li\n key={row.node.id}\n role=\"treeitem\"\n aria-expanded={row.hasChildren ? row.expanded : undefined}\n aria-selected={isSelected}\n aria-level={row.depth + 1}\n aria-disabled={row.node.disabled || undefined}\n className={styles.item}\n >\n <div\n data-tree-id={row.node.id}\n className={cn(\n styles.row,\n isSelected && styles.selected,\n row.node.disabled && styles.disabled,\n )}\n style={{\n paddingInlineStart: `calc(${row.depth} * var(--tempest-space-5))`,\n }}\n tabIndex={activeId === row.node.id && !row.node.disabled ? 0 : -1}\n onClick={() => select(row)}\n onFocus={() => setFocusedId(row.node.id)}\n onKeyDown={(event) => handleKeyDown(event, row, index)}\n >\n {row.hasChildren ? (\n <span\n className={cn(\n styles.chevron,\n row.expanded && styles.chevronOpen,\n )}\n aria-hidden=\"true\"\n onClick={(event) => {\n event.stopPropagation();\n if (!row.node.disabled) toggle(row.node.id);\n }}\n >\n <ChevronRight size={14} />\n </span>\n ) : (\n <span className={styles.chevronPlaceholder} aria-hidden=\"true\" />\n )}\n {row.node.icon ? (\n <span className={styles.icon} aria-hidden=\"true\">\n {row.node.icon}\n </span>\n ) : null}\n <span className={styles.label}>{row.node.label}</span>\n </div>\n </li>\n );\n })}\n </ul>\n );\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
var e=`tempest_tree_velMm`,t=`tempest_item_A2xw2`,n=`tempest_row_BsqpV`,r=`tempest_selected_uhjg8`,i=`tempest_disabled_vKxfJ`,a=`tempest_chevron_5v99r`,o=`tempest_chevronOpen_H3jAu`,s=`tempest_chevronPlaceholder_j0xjc`,c=`tempest_icon_O4r1C`,l=`tempest_label_MqR1B`,u={tree:e,item:t,row:n,selected:r,disabled:i,chevron:a,chevronOpen:o,chevronPlaceholder:s,icon:c,label:l};exports.chevron=a,exports.chevronOpen=o,exports.chevronPlaceholder=s,exports.default=u,exports.disabled=i,exports.icon=c,exports.item=t,exports.label=l,exports.row=n,exports.selected=r,exports.tree=e;
|
|
2
|
+
//# sourceMappingURL=TreeView.module.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"TreeView.module.cjs","names":[],"sources":["../../../src/components/TreeView/TreeView.module.css"],"sourcesContent":[".tree {\n display: flex;\n flex-direction: column;\n margin: 0;\n padding: 0;\n list-style: none;\n color: var(--tempest-text);\n font-size: var(--tempest-text-sm);\n}\n\n.item {\n margin: 0;\n padding: 0;\n list-style: none;\n}\n\n.row {\n display: flex;\n align-items: center;\n gap: var(--tempest-space-2);\n width: 100%;\n padding-block: var(--tempest-space-2);\n padding-inline-end: var(--tempest-space-3);\n border-radius: var(--tempest-radius-sm);\n cursor: pointer;\n user-select: none;\n transition:\n background-color var(--tempest-duration-fast) var(--tempest-ease-out),\n color var(--tempest-duration-fast) var(--tempest-ease-out);\n}\n\n.row:hover {\n background-color: var(--tempest-surface-2);\n}\n\n.row:focus-visible {\n outline: var(--tempest-focus-ring-width) solid var(--tempest-focus-ring-color);\n outline-offset: calc(var(--tempest-focus-ring-offset) * -1);\n}\n\n.selected {\n background-color: var(--tempest-primary-soft);\n color: var(--tempest-primary-on-soft);\n font-weight: var(--tempest-weight-medium);\n}\n\n.selected:hover {\n background-color: var(--tempest-primary-soft-hover);\n}\n\n.disabled {\n color: var(--tempest-text-subtle);\n cursor: not-allowed;\n}\n\n.disabled:hover {\n background-color: transparent;\n}\n\n.chevron {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n flex: 0 0 auto;\n width: 18px;\n height: 18px;\n border-radius: var(--tempest-radius-xs);\n color: var(--tempest-text-muted);\n transition: transform var(--tempest-duration-fast) var(--tempest-ease-out);\n}\n\n.chevron:hover {\n background-color: var(--tempest-surface-3);\n}\n\n.chevronOpen {\n transform: rotate(90deg);\n}\n\n.chevronPlaceholder {\n display: inline-block;\n flex: 0 0 auto;\n width: 18px;\n height: 18px;\n}\n\n.icon {\n display: inline-flex;\n align-items: center;\n flex: 0 0 auto;\n color: var(--tempest-text-muted);\n}\n\n.label {\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n@media (prefers-reduced-motion: reduce) {\n .row,\n .chevron {\n transition: none;\n }\n}\n"],"mappings":""}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
//#region src/components/TreeView/TreeView.module.css
|
|
2
|
+
var e = "tempest_tree_velMm", t = "tempest_item_A2xw2", n = "tempest_row_BsqpV", r = "tempest_selected_uhjg8", i = "tempest_disabled_vKxfJ", a = "tempest_chevron_5v99r", o = "tempest_chevronOpen_H3jAu", s = "tempest_chevronPlaceholder_j0xjc", c = "tempest_icon_O4r1C", l = "tempest_label_MqR1B", u = {
|
|
3
|
+
tree: e,
|
|
4
|
+
item: t,
|
|
5
|
+
row: n,
|
|
6
|
+
selected: r,
|
|
7
|
+
disabled: i,
|
|
8
|
+
chevron: a,
|
|
9
|
+
chevronOpen: o,
|
|
10
|
+
chevronPlaceholder: s,
|
|
11
|
+
icon: c,
|
|
12
|
+
label: l
|
|
13
|
+
};
|
|
14
|
+
//#endregion
|
|
15
|
+
export { a as chevron, o as chevronOpen, s as chevronPlaceholder, u as default, i as disabled, c as icon, t as item, l as label, n as row, r as selected, e as tree };
|
|
16
|
+
|
|
17
|
+
//# sourceMappingURL=TreeView.module.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"TreeView.module.js","names":[],"sources":["../../../src/components/TreeView/TreeView.module.css"],"sourcesContent":[".tree {\n display: flex;\n flex-direction: column;\n margin: 0;\n padding: 0;\n list-style: none;\n color: var(--tempest-text);\n font-size: var(--tempest-text-sm);\n}\n\n.item {\n margin: 0;\n padding: 0;\n list-style: none;\n}\n\n.row {\n display: flex;\n align-items: center;\n gap: var(--tempest-space-2);\n width: 100%;\n padding-block: var(--tempest-space-2);\n padding-inline-end: var(--tempest-space-3);\n border-radius: var(--tempest-radius-sm);\n cursor: pointer;\n user-select: none;\n transition:\n background-color var(--tempest-duration-fast) var(--tempest-ease-out),\n color var(--tempest-duration-fast) var(--tempest-ease-out);\n}\n\n.row:hover {\n background-color: var(--tempest-surface-2);\n}\n\n.row:focus-visible {\n outline: var(--tempest-focus-ring-width) solid var(--tempest-focus-ring-color);\n outline-offset: calc(var(--tempest-focus-ring-offset) * -1);\n}\n\n.selected {\n background-color: var(--tempest-primary-soft);\n color: var(--tempest-primary-on-soft);\n font-weight: var(--tempest-weight-medium);\n}\n\n.selected:hover {\n background-color: var(--tempest-primary-soft-hover);\n}\n\n.disabled {\n color: var(--tempest-text-subtle);\n cursor: not-allowed;\n}\n\n.disabled:hover {\n background-color: transparent;\n}\n\n.chevron {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n flex: 0 0 auto;\n width: 18px;\n height: 18px;\n border-radius: var(--tempest-radius-xs);\n color: var(--tempest-text-muted);\n transition: transform var(--tempest-duration-fast) var(--tempest-ease-out);\n}\n\n.chevron:hover {\n background-color: var(--tempest-surface-3);\n}\n\n.chevronOpen {\n transform: rotate(90deg);\n}\n\n.chevronPlaceholder {\n display: inline-block;\n flex: 0 0 auto;\n width: 18px;\n height: 18px;\n}\n\n.icon {\n display: inline-flex;\n align-items: center;\n flex: 0 0 auto;\n color: var(--tempest-text-muted);\n}\n\n.label {\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n@media (prefers-reduced-motion: reduce) {\n .row,\n .chevron {\n transition: none;\n }\n}\n"],"mappings":""}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
const e=require("../../utils/cn.cjs"),t=require("../../utils/compare-values.cjs"),n=require("./VirtualTable.module.cjs");let r=require("react"),i=require("react/jsx-runtime");function a(e){if(e===`right`)return n.default.alignRight;if(e===`center`)return n.default.alignCenter}function o({data:o,columns:s,rowHeight:c,height:l,overscan:u=4,rowKey:d,initialSort:f,onRowClick:p,emptyMessage:m=`Nenhum registro encontrado.`,caption:h,scrollToIndex:g,className:_,...v}){let y=(0,r.useRef)(null),[b,x]=(0,r.useState)(0),[S,C]=(0,r.useState)(0),[w,T]=(0,r.useState)(f??null);(0,r.useEffect)(()=>{let e=y.current;if(!e||(C(e.clientHeight),typeof ResizeObserver>`u`))return;let t=new ResizeObserver(()=>C(e.clientHeight));return t.observe(e),()=>t.disconnect()},[]),(0,r.useEffect)(()=>{let e=y.current;!e||g==null||(e.scrollTop=Math.max(0,Math.min(g,o.length-1))*c)},[g,c,o.length]);let E=(0,r.useMemo)(()=>{if(!w)return o;let e=w.direction===`asc`?1:-1;return[...o].sort((n,r)=>t.compareValues(n[w.key],r[w.key])*e)},[o,w]),D=Math.max(0,Math.floor(b/c)-u),O=Math.ceil(S/c)+u*2,k=Math.min(E.length,D+O),A=E.slice(D,k),j=(0,r.useCallback)(e=>{T(t=>!t||t.key!==e?{key:e,direction:`asc`}:t.direction===`asc`?{key:e,direction:`desc`}:null);let t=y.current;t&&(t.scrollTop=0),x(0)},[]);return(0,i.jsx)(`div`,{ref:y,className:e.cn(n.default.scroll,_),style:{height:l},onScroll:e=>x(e.currentTarget.scrollTop),...v,children:(0,i.jsxs)(`table`,{className:n.default.table,"aria-rowcount":E.length,children:[h?(0,i.jsx)(`caption`,{className:n.default.caption,children:h}):null,(0,i.jsx)(`thead`,{className:n.default.head,children:(0,i.jsx)(`tr`,{children:s.map(t=>{let r=w?.key===t.key;return(0,i.jsx)(`th`,{scope:`col`,className:e.cn(n.default.th,a(t.align)),style:{width:t.width},"aria-sort":r?w?.direction===`asc`?`ascending`:`descending`:t.sortable?`none`:void 0,children:t.sortable?(0,i.jsxs)(`button`,{type:`button`,className:n.default.sortButton,onClick:()=>j(t.key),children:[t.header,(0,i.jsx)(`span`,{className:n.default.sortIndicator,"aria-hidden":!0,children:r?w?.direction===`asc`?`▲`:`▼`:`↕`})]}):t.header},String(t.key))})})}),(0,i.jsx)(`tbody`,{children:E.length===0?(0,i.jsx)(`tr`,{children:(0,i.jsx)(`td`,{className:n.default.emptyRow,colSpan:s.length,children:m})}):(0,i.jsxs)(i.Fragment,{children:[D>0&&(0,i.jsx)(`tr`,{"aria-hidden":!0,style:{height:D*c}}),A.map((t,r)=>{let o=D+r;return(0,i.jsx)(`tr`,{"aria-rowindex":o+1,className:e.cn(n.default.tr,p&&n.default.clickable),style:{height:c},tabIndex:p?0:void 0,onClick:p?()=>p(t,o):void 0,onKeyDown:p?e=>{(e.key===`Enter`||e.key===` `)&&(e.preventDefault(),p(t,o))}:void 0,children:s.map(r=>(0,i.jsx)(`td`,{className:e.cn(n.default.td,a(r.align)),style:{width:r.width},children:r.render?r.render(t,o):t[r.key]??null},String(r.key)))},d?d(t,o):o)}),k<E.length&&(0,i.jsx)(`tr`,{"aria-hidden":!0,style:{height:(E.length-k)*c}})]})})]})})}exports.VirtualTable=o;
|
|
2
|
+
//# sourceMappingURL=VirtualTable.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"VirtualTable.cjs","names":[],"sources":["../../../src/components/VirtualTable/VirtualTable.tsx"],"sourcesContent":["import {\n type HTMLAttributes,\n type ReactNode,\n useCallback,\n useEffect,\n useMemo,\n useRef,\n useState,\n} from \"react\";\n\nimport { cn } from \"@/utils/cn\";\nimport { compareValues } from \"@/utils/compare-values\";\n\nimport type { TableAlign } from \"../Table\";\nimport styles from \"./VirtualTable.module.css\";\n\nexport type VirtualTableSortDirection = \"asc\" | \"desc\";\n\nexport interface VirtualTableSort<T> {\n key: keyof T;\n direction: VirtualTableSortDirection;\n}\n\nexport interface VirtualTableColumn<T> {\n /** Property of the row this column reads from. Doubles as the cell key. */\n key: keyof T;\n /** Column heading. */\n header: ReactNode;\n /** Custom cell renderer. Defaults to `row[key]`. */\n render?: (row: T, index: number) => ReactNode;\n /** Enable click-to-sort on this column's header. */\n sortable?: boolean;\n /** Text alignment. */\n align?: TableAlign;\n /**\n * Column width. Recommended for every column: virtualized rows enter and\n * leave the DOM as you scroll, so letting the browser auto-size columns from\n * whatever is currently rendered makes them jump mid-scroll.\n */\n width?: string | number;\n}\n\nexport interface VirtualTableProps<T> extends Omit<HTMLAttributes<HTMLDivElement>, \"children\"> {\n /** Full dataset. Every row is accounted for; only the visible ones render. */\n data: T[];\n /** Column definitions. */\n columns: VirtualTableColumn<T>[];\n /**\n * Row height in px. Must be uniform and must match what the CSS produces,\n * because it is what maps scroll offset to row index.\n */\n rowHeight: number;\n /** Height of the scroll viewport — a number of px or any CSS length. */\n height: number | string;\n /** Rows rendered above and below the viewport. Default `4`. */\n overscan?: number;\n /** Stable key extractor. Defaults to the row's index in `data`. */\n rowKey?: (row: T, index: number) => string | number;\n /** Sort applied before any header interaction. */\n initialSort?: VirtualTableSort<T>;\n /** Called when a row is activated by click, `Enter` or `Space`. */\n onRowClick?: (row: T, index: number) => void;\n /** Content shown when `data` is empty. */\n emptyMessage?: ReactNode;\n /** Accessible name for the table. Rendered as a visually hidden `<caption>`. */\n caption?: ReactNode;\n /** Scroll this row into view whenever it changes. */\n scrollToIndex?: number;\n}\n\n/** Resolve a column's alignment to its CSS module class. */\nfunction alignClass(align: TableAlign | undefined): string | undefined {\n if (align === \"right\") return styles.alignRight;\n if (align === \"center\") return styles.alignCenter;\n return undefined;\n}\n\n/**\n * A table that stays responsive at 10k+ rows by rendering only the visible window.\n *\n * `Table` renders every row it is given and `DataTable` paginates to keep that\n * count small; neither has an answer for \"show me all 40 000 rows in one\n * scrollable grid\". This does, at the cost of one constraint: **`rowHeight` must\n * be uniform**, since mapping a scroll offset to a row index is what makes the\n * window computable without measuring anything.\n *\n * It stays a real `<table>`. The window is produced by two spacer rows — one\n * above the visible slice, one below — instead of absolutely positioning rows.\n * That is deliberate: `position: absolute` on `<tr>` collapses table layout, so\n * every column width would have to be computed by hand, and the element would\n * stop being a table for assistive technology. With spacer rows the browser keeps\n * doing column layout and screen readers keep announcing a grid.\n *\n * Because only a slice is in the DOM, `aria-rowcount` on the table and\n * `aria-rowindex` on each row carry the real numbers — without them a screen\n * reader announces \"row 3 of 20\" while the user is on row 5003 of 40 000.\n *\n * @example\n * <VirtualTable\n * data={rows}\n * columns={[\n * { key: \"id\", header: \"#\", width: 80, sortable: true },\n * { key: \"name\", header: \"Nome\", width: 240, sortable: true },\n * { key: \"total\", header: \"Total\", align: \"right\", width: 120, sortable: true },\n * ]}\n * rowHeight={40}\n * height={480}\n * rowKey={(row) => row.id}\n * />\n */\nexport function VirtualTable<T>({\n data,\n columns,\n rowHeight,\n height,\n overscan = 4,\n rowKey,\n initialSort,\n onRowClick,\n emptyMessage = \"Nenhum registro encontrado.\",\n caption,\n scrollToIndex,\n className,\n ...rest\n}: VirtualTableProps<T>) {\n const scrollRef = useRef<HTMLDivElement>(null);\n const [scrollTop, setScrollTop] = useState<number>(0);\n const [viewport, setViewport] = useState<number>(0);\n const [sort, setSort] = useState<VirtualTableSort<T> | null>(initialSort ?? null);\n\n useEffect(() => {\n const element = scrollRef.current;\n if (!element) return;\n setViewport(element.clientHeight);\n if (typeof ResizeObserver === \"undefined\") return;\n const observer = new ResizeObserver(() => setViewport(element.clientHeight));\n observer.observe(element);\n return () => observer.disconnect();\n }, []);\n\n useEffect(() => {\n const element = scrollRef.current;\n if (!element || scrollToIndex == null) return;\n element.scrollTop = Math.max(0, Math.min(scrollToIndex, data.length - 1)) * rowHeight;\n }, [scrollToIndex, rowHeight, data.length]);\n\n const sorted = useMemo<T[]>(() => {\n if (!sort) return data;\n const factor = sort.direction === \"asc\" ? 1 : -1;\n return [...data].sort((a, b) => compareValues(a[sort.key], b[sort.key]) * factor);\n }, [data, sort]);\n\n const start = Math.max(0, Math.floor(scrollTop / rowHeight) - overscan);\n const windowSize = Math.ceil(viewport / rowHeight) + overscan * 2;\n const end = Math.min(sorted.length, start + windowSize);\n const slice = sorted.slice(start, end);\n\n /**\n * Advance a column through asc → desc → unsorted, and jump back to the top.\n *\n * The scroll reset happens here rather than in an effect keyed on the sort\n * state for two reasons: this is the actual event that invalidates the offset\n * (keeping it would leave the user at the same pixel of a different dataset,\n * which reads as the table having jumped somewhere random), and an effect would\n * also fire on mount — clobbering an initial `scrollToIndex`.\n */\n const toggleSort = useCallback((key: keyof T): void => {\n setSort((current) => {\n if (!current || current.key !== key) return { key, direction: \"asc\" };\n if (current.direction === \"asc\") return { key, direction: \"desc\" };\n return null;\n });\n const element = scrollRef.current;\n if (element) element.scrollTop = 0;\n setScrollTop(0);\n }, []);\n\n return (\n <div\n ref={scrollRef}\n className={cn(styles.scroll, className)}\n style={{ height }}\n onScroll={(event) => setScrollTop(event.currentTarget.scrollTop)}\n {...rest}\n >\n <table className={styles.table} aria-rowcount={sorted.length}>\n {caption ? <caption className={styles.caption}>{caption}</caption> : null}\n <thead className={styles.head}>\n <tr>\n {columns.map((column) => {\n const isSorted = sort?.key === column.key;\n return (\n <th\n key={String(column.key)}\n scope=\"col\"\n className={cn(styles.th, alignClass(column.align))}\n style={{ width: column.width }}\n aria-sort={\n isSorted\n ? sort?.direction === \"asc\"\n ? \"ascending\"\n : \"descending\"\n : column.sortable\n ? \"none\"\n : undefined\n }\n >\n {column.sortable ? (\n <button\n type=\"button\"\n className={styles.sortButton}\n onClick={() => toggleSort(column.key)}\n >\n {column.header}\n <span className={styles.sortIndicator} aria-hidden>\n {isSorted\n ? sort?.direction === \"asc\"\n ? \"▲\"\n : \"▼\"\n : \"↕\"}\n </span>\n </button>\n ) : (\n column.header\n )}\n </th>\n );\n })}\n </tr>\n </thead>\n <tbody>\n {sorted.length === 0 ? (\n <tr>\n <td className={styles.emptyRow} colSpan={columns.length}>\n {emptyMessage}\n </td>\n </tr>\n ) : (\n <>\n {start > 0 && <tr aria-hidden style={{ height: start * rowHeight }} />}\n {slice.map((row, offset) => {\n const index = start + offset;\n return (\n <tr\n key={rowKey ? rowKey(row, index) : index}\n aria-rowindex={index + 1}\n className={cn(styles.tr, onRowClick && styles.clickable)}\n style={{ height: rowHeight }}\n tabIndex={onRowClick ? 0 : undefined}\n onClick={\n onRowClick ? () => onRowClick(row, index) : undefined\n }\n onKeyDown={\n onRowClick\n ? (event) => {\n if (\n event.key === \"Enter\" ||\n event.key === \" \"\n ) {\n event.preventDefault();\n onRowClick(row, index);\n }\n }\n : undefined\n }\n >\n {columns.map((column) => (\n <td\n key={String(column.key)}\n className={cn(styles.td, alignClass(column.align))}\n style={{ width: column.width }}\n >\n {column.render\n ? column.render(row, index)\n : ((row[column.key] as ReactNode) ?? null)}\n </td>\n ))}\n </tr>\n );\n })}\n {end < sorted.length && (\n <tr\n aria-hidden\n style={{ height: (sorted.length - end) * rowHeight }}\n />\n )}\n </>\n )}\n </tbody>\n </table>\n </div>\n );\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
import { cn as e } from "../../utils/cn.js";
|
|
2
|
+
import { compareValues as t } from "../../utils/compare-values.js";
|
|
3
|
+
import n from "./VirtualTable.module.js";
|
|
4
|
+
import { useCallback as r, useEffect as i, useMemo as a, useRef as o, useState as s } from "react";
|
|
5
|
+
import { Fragment as c, jsx as l, jsxs as u } from "react/jsx-runtime";
|
|
6
|
+
//#region src/components/VirtualTable/VirtualTable.tsx
|
|
7
|
+
function d(e) {
|
|
8
|
+
if (e === "right") return n.alignRight;
|
|
9
|
+
if (e === "center") return n.alignCenter;
|
|
10
|
+
}
|
|
11
|
+
function f({ data: f, columns: p, rowHeight: m, height: h, overscan: g = 4, rowKey: _, initialSort: v, onRowClick: y, emptyMessage: b = "Nenhum registro encontrado.", caption: x, scrollToIndex: S, className: C, ...w }) {
|
|
12
|
+
let T = o(null), [E, D] = s(0), [O, k] = s(0), [A, j] = s(v ?? null);
|
|
13
|
+
i(() => {
|
|
14
|
+
let e = T.current;
|
|
15
|
+
if (!e || (k(e.clientHeight), typeof ResizeObserver > "u")) return;
|
|
16
|
+
let t = new ResizeObserver(() => k(e.clientHeight));
|
|
17
|
+
return t.observe(e), () => t.disconnect();
|
|
18
|
+
}, []), i(() => {
|
|
19
|
+
let e = T.current;
|
|
20
|
+
!e || S == null || (e.scrollTop = Math.max(0, Math.min(S, f.length - 1)) * m);
|
|
21
|
+
}, [
|
|
22
|
+
S,
|
|
23
|
+
m,
|
|
24
|
+
f.length
|
|
25
|
+
]);
|
|
26
|
+
let M = a(() => {
|
|
27
|
+
if (!A) return f;
|
|
28
|
+
let e = A.direction === "asc" ? 1 : -1;
|
|
29
|
+
return [...f].sort((n, r) => t(n[A.key], r[A.key]) * e);
|
|
30
|
+
}, [f, A]), N = Math.max(0, Math.floor(E / m) - g), P = Math.ceil(O / m) + g * 2, F = Math.min(M.length, N + P), I = M.slice(N, F), L = r((e) => {
|
|
31
|
+
j((t) => !t || t.key !== e ? {
|
|
32
|
+
key: e,
|
|
33
|
+
direction: "asc"
|
|
34
|
+
} : t.direction === "asc" ? {
|
|
35
|
+
key: e,
|
|
36
|
+
direction: "desc"
|
|
37
|
+
} : null);
|
|
38
|
+
let t = T.current;
|
|
39
|
+
t && (t.scrollTop = 0), D(0);
|
|
40
|
+
}, []);
|
|
41
|
+
return /* @__PURE__ */ l("div", {
|
|
42
|
+
ref: T,
|
|
43
|
+
className: e(n.scroll, C),
|
|
44
|
+
style: { height: h },
|
|
45
|
+
onScroll: (e) => D(e.currentTarget.scrollTop),
|
|
46
|
+
...w,
|
|
47
|
+
children: /* @__PURE__ */ u("table", {
|
|
48
|
+
className: n.table,
|
|
49
|
+
"aria-rowcount": M.length,
|
|
50
|
+
children: [
|
|
51
|
+
x ? /* @__PURE__ */ l("caption", {
|
|
52
|
+
className: n.caption,
|
|
53
|
+
children: x
|
|
54
|
+
}) : null,
|
|
55
|
+
/* @__PURE__ */ l("thead", {
|
|
56
|
+
className: n.head,
|
|
57
|
+
children: /* @__PURE__ */ l("tr", { children: p.map((t) => {
|
|
58
|
+
let r = A?.key === t.key;
|
|
59
|
+
return /* @__PURE__ */ l("th", {
|
|
60
|
+
scope: "col",
|
|
61
|
+
className: e(n.th, d(t.align)),
|
|
62
|
+
style: { width: t.width },
|
|
63
|
+
"aria-sort": r ? A?.direction === "asc" ? "ascending" : "descending" : t.sortable ? "none" : void 0,
|
|
64
|
+
children: t.sortable ? /* @__PURE__ */ u("button", {
|
|
65
|
+
type: "button",
|
|
66
|
+
className: n.sortButton,
|
|
67
|
+
onClick: () => L(t.key),
|
|
68
|
+
children: [t.header, /* @__PURE__ */ l("span", {
|
|
69
|
+
className: n.sortIndicator,
|
|
70
|
+
"aria-hidden": !0,
|
|
71
|
+
children: r ? A?.direction === "asc" ? "▲" : "▼" : "↕"
|
|
72
|
+
})]
|
|
73
|
+
}) : t.header
|
|
74
|
+
}, String(t.key));
|
|
75
|
+
}) })
|
|
76
|
+
}),
|
|
77
|
+
/* @__PURE__ */ l("tbody", { children: M.length === 0 ? /* @__PURE__ */ l("tr", { children: /* @__PURE__ */ l("td", {
|
|
78
|
+
className: n.emptyRow,
|
|
79
|
+
colSpan: p.length,
|
|
80
|
+
children: b
|
|
81
|
+
}) }) : /* @__PURE__ */ u(c, { children: [
|
|
82
|
+
N > 0 && /* @__PURE__ */ l("tr", {
|
|
83
|
+
"aria-hidden": !0,
|
|
84
|
+
style: { height: N * m }
|
|
85
|
+
}),
|
|
86
|
+
I.map((t, r) => {
|
|
87
|
+
let i = N + r;
|
|
88
|
+
return /* @__PURE__ */ l("tr", {
|
|
89
|
+
"aria-rowindex": i + 1,
|
|
90
|
+
className: e(n.tr, y && n.clickable),
|
|
91
|
+
style: { height: m },
|
|
92
|
+
tabIndex: y ? 0 : void 0,
|
|
93
|
+
onClick: y ? () => y(t, i) : void 0,
|
|
94
|
+
onKeyDown: y ? (e) => {
|
|
95
|
+
(e.key === "Enter" || e.key === " ") && (e.preventDefault(), y(t, i));
|
|
96
|
+
} : void 0,
|
|
97
|
+
children: p.map((r) => /* @__PURE__ */ l("td", {
|
|
98
|
+
className: e(n.td, d(r.align)),
|
|
99
|
+
style: { width: r.width },
|
|
100
|
+
children: r.render ? r.render(t, i) : t[r.key] ?? null
|
|
101
|
+
}, String(r.key)))
|
|
102
|
+
}, _ ? _(t, i) : i);
|
|
103
|
+
}),
|
|
104
|
+
F < M.length && /* @__PURE__ */ l("tr", {
|
|
105
|
+
"aria-hidden": !0,
|
|
106
|
+
style: { height: (M.length - F) * m }
|
|
107
|
+
})
|
|
108
|
+
] }) })
|
|
109
|
+
]
|
|
110
|
+
})
|
|
111
|
+
});
|
|
112
|
+
}
|
|
113
|
+
//#endregion
|
|
114
|
+
export { f as VirtualTable };
|
|
115
|
+
|
|
116
|
+
//# sourceMappingURL=VirtualTable.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"VirtualTable.js","names":[],"sources":["../../../src/components/VirtualTable/VirtualTable.tsx"],"sourcesContent":["import {\n type HTMLAttributes,\n type ReactNode,\n useCallback,\n useEffect,\n useMemo,\n useRef,\n useState,\n} from \"react\";\n\nimport { cn } from \"@/utils/cn\";\nimport { compareValues } from \"@/utils/compare-values\";\n\nimport type { TableAlign } from \"../Table\";\nimport styles from \"./VirtualTable.module.css\";\n\nexport type VirtualTableSortDirection = \"asc\" | \"desc\";\n\nexport interface VirtualTableSort<T> {\n key: keyof T;\n direction: VirtualTableSortDirection;\n}\n\nexport interface VirtualTableColumn<T> {\n /** Property of the row this column reads from. Doubles as the cell key. */\n key: keyof T;\n /** Column heading. */\n header: ReactNode;\n /** Custom cell renderer. Defaults to `row[key]`. */\n render?: (row: T, index: number) => ReactNode;\n /** Enable click-to-sort on this column's header. */\n sortable?: boolean;\n /** Text alignment. */\n align?: TableAlign;\n /**\n * Column width. Recommended for every column: virtualized rows enter and\n * leave the DOM as you scroll, so letting the browser auto-size columns from\n * whatever is currently rendered makes them jump mid-scroll.\n */\n width?: string | number;\n}\n\nexport interface VirtualTableProps<T> extends Omit<HTMLAttributes<HTMLDivElement>, \"children\"> {\n /** Full dataset. Every row is accounted for; only the visible ones render. */\n data: T[];\n /** Column definitions. */\n columns: VirtualTableColumn<T>[];\n /**\n * Row height in px. Must be uniform and must match what the CSS produces,\n * because it is what maps scroll offset to row index.\n */\n rowHeight: number;\n /** Height of the scroll viewport — a number of px or any CSS length. */\n height: number | string;\n /** Rows rendered above and below the viewport. Default `4`. */\n overscan?: number;\n /** Stable key extractor. Defaults to the row's index in `data`. */\n rowKey?: (row: T, index: number) => string | number;\n /** Sort applied before any header interaction. */\n initialSort?: VirtualTableSort<T>;\n /** Called when a row is activated by click, `Enter` or `Space`. */\n onRowClick?: (row: T, index: number) => void;\n /** Content shown when `data` is empty. */\n emptyMessage?: ReactNode;\n /** Accessible name for the table. Rendered as a visually hidden `<caption>`. */\n caption?: ReactNode;\n /** Scroll this row into view whenever it changes. */\n scrollToIndex?: number;\n}\n\n/** Resolve a column's alignment to its CSS module class. */\nfunction alignClass(align: TableAlign | undefined): string | undefined {\n if (align === \"right\") return styles.alignRight;\n if (align === \"center\") return styles.alignCenter;\n return undefined;\n}\n\n/**\n * A table that stays responsive at 10k+ rows by rendering only the visible window.\n *\n * `Table` renders every row it is given and `DataTable` paginates to keep that\n * count small; neither has an answer for \"show me all 40 000 rows in one\n * scrollable grid\". This does, at the cost of one constraint: **`rowHeight` must\n * be uniform**, since mapping a scroll offset to a row index is what makes the\n * window computable without measuring anything.\n *\n * It stays a real `<table>`. The window is produced by two spacer rows — one\n * above the visible slice, one below — instead of absolutely positioning rows.\n * That is deliberate: `position: absolute` on `<tr>` collapses table layout, so\n * every column width would have to be computed by hand, and the element would\n * stop being a table for assistive technology. With spacer rows the browser keeps\n * doing column layout and screen readers keep announcing a grid.\n *\n * Because only a slice is in the DOM, `aria-rowcount` on the table and\n * `aria-rowindex` on each row carry the real numbers — without them a screen\n * reader announces \"row 3 of 20\" while the user is on row 5003 of 40 000.\n *\n * @example\n * <VirtualTable\n * data={rows}\n * columns={[\n * { key: \"id\", header: \"#\", width: 80, sortable: true },\n * { key: \"name\", header: \"Nome\", width: 240, sortable: true },\n * { key: \"total\", header: \"Total\", align: \"right\", width: 120, sortable: true },\n * ]}\n * rowHeight={40}\n * height={480}\n * rowKey={(row) => row.id}\n * />\n */\nexport function VirtualTable<T>({\n data,\n columns,\n rowHeight,\n height,\n overscan = 4,\n rowKey,\n initialSort,\n onRowClick,\n emptyMessage = \"Nenhum registro encontrado.\",\n caption,\n scrollToIndex,\n className,\n ...rest\n}: VirtualTableProps<T>) {\n const scrollRef = useRef<HTMLDivElement>(null);\n const [scrollTop, setScrollTop] = useState<number>(0);\n const [viewport, setViewport] = useState<number>(0);\n const [sort, setSort] = useState<VirtualTableSort<T> | null>(initialSort ?? null);\n\n useEffect(() => {\n const element = scrollRef.current;\n if (!element) return;\n setViewport(element.clientHeight);\n if (typeof ResizeObserver === \"undefined\") return;\n const observer = new ResizeObserver(() => setViewport(element.clientHeight));\n observer.observe(element);\n return () => observer.disconnect();\n }, []);\n\n useEffect(() => {\n const element = scrollRef.current;\n if (!element || scrollToIndex == null) return;\n element.scrollTop = Math.max(0, Math.min(scrollToIndex, data.length - 1)) * rowHeight;\n }, [scrollToIndex, rowHeight, data.length]);\n\n const sorted = useMemo<T[]>(() => {\n if (!sort) return data;\n const factor = sort.direction === \"asc\" ? 1 : -1;\n return [...data].sort((a, b) => compareValues(a[sort.key], b[sort.key]) * factor);\n }, [data, sort]);\n\n const start = Math.max(0, Math.floor(scrollTop / rowHeight) - overscan);\n const windowSize = Math.ceil(viewport / rowHeight) + overscan * 2;\n const end = Math.min(sorted.length, start + windowSize);\n const slice = sorted.slice(start, end);\n\n /**\n * Advance a column through asc → desc → unsorted, and jump back to the top.\n *\n * The scroll reset happens here rather than in an effect keyed on the sort\n * state for two reasons: this is the actual event that invalidates the offset\n * (keeping it would leave the user at the same pixel of a different dataset,\n * which reads as the table having jumped somewhere random), and an effect would\n * also fire on mount — clobbering an initial `scrollToIndex`.\n */\n const toggleSort = useCallback((key: keyof T): void => {\n setSort((current) => {\n if (!current || current.key !== key) return { key, direction: \"asc\" };\n if (current.direction === \"asc\") return { key, direction: \"desc\" };\n return null;\n });\n const element = scrollRef.current;\n if (element) element.scrollTop = 0;\n setScrollTop(0);\n }, []);\n\n return (\n <div\n ref={scrollRef}\n className={cn(styles.scroll, className)}\n style={{ height }}\n onScroll={(event) => setScrollTop(event.currentTarget.scrollTop)}\n {...rest}\n >\n <table className={styles.table} aria-rowcount={sorted.length}>\n {caption ? <caption className={styles.caption}>{caption}</caption> : null}\n <thead className={styles.head}>\n <tr>\n {columns.map((column) => {\n const isSorted = sort?.key === column.key;\n return (\n <th\n key={String(column.key)}\n scope=\"col\"\n className={cn(styles.th, alignClass(column.align))}\n style={{ width: column.width }}\n aria-sort={\n isSorted\n ? sort?.direction === \"asc\"\n ? \"ascending\"\n : \"descending\"\n : column.sortable\n ? \"none\"\n : undefined\n }\n >\n {column.sortable ? (\n <button\n type=\"button\"\n className={styles.sortButton}\n onClick={() => toggleSort(column.key)}\n >\n {column.header}\n <span className={styles.sortIndicator} aria-hidden>\n {isSorted\n ? sort?.direction === \"asc\"\n ? \"▲\"\n : \"▼\"\n : \"↕\"}\n </span>\n </button>\n ) : (\n column.header\n )}\n </th>\n );\n })}\n </tr>\n </thead>\n <tbody>\n {sorted.length === 0 ? (\n <tr>\n <td className={styles.emptyRow} colSpan={columns.length}>\n {emptyMessage}\n </td>\n </tr>\n ) : (\n <>\n {start > 0 && <tr aria-hidden style={{ height: start * rowHeight }} />}\n {slice.map((row, offset) => {\n const index = start + offset;\n return (\n <tr\n key={rowKey ? rowKey(row, index) : index}\n aria-rowindex={index + 1}\n className={cn(styles.tr, onRowClick && styles.clickable)}\n style={{ height: rowHeight }}\n tabIndex={onRowClick ? 0 : undefined}\n onClick={\n onRowClick ? () => onRowClick(row, index) : undefined\n }\n onKeyDown={\n onRowClick\n ? (event) => {\n if (\n event.key === \"Enter\" ||\n event.key === \" \"\n ) {\n event.preventDefault();\n onRowClick(row, index);\n }\n }\n : undefined\n }\n >\n {columns.map((column) => (\n <td\n key={String(column.key)}\n className={cn(styles.td, alignClass(column.align))}\n style={{ width: column.width }}\n >\n {column.render\n ? column.render(row, index)\n : ((row[column.key] as ReactNode) ?? null)}\n </td>\n ))}\n </tr>\n );\n })}\n {end < sorted.length && (\n <tr\n aria-hidden\n style={{ height: (sorted.length - end) * rowHeight }}\n />\n )}\n </>\n )}\n </tbody>\n </table>\n </div>\n );\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
var e=`tempest_scroll_XOPRs`,t=`tempest_table_wbJg-`,n=`tempest_caption_Dt-O5`,r=`tempest_head_9xVmx`,i=`tempest_th_-xzNL`,a=`tempest_td_Crp7i`,o=`tempest_alignRight_uxhpx`,s=`tempest_alignCenter_9B3Sb`,c=`tempest_sortButton_4h-vK`,l=`tempest_sortIndicator_-WpMp`,u=`tempest_tr_EI3uW`,d=`tempest_clickable_4AfSX`,f=`tempest_emptyRow_4kIiT`,p={scroll:e,table:t,caption:n,head:r,th:i,td:a,alignRight:o,alignCenter:s,sortButton:c,sortIndicator:l,tr:u,clickable:d,emptyRow:f};exports.alignCenter=s,exports.alignRight=o,exports.caption=n,exports.clickable=d,exports.default=p,exports.emptyRow=f,exports.head=r,exports.scroll=e,exports.sortButton=c,exports.sortIndicator=l,exports.table=t,exports.td=a,exports.th=i,exports.tr=u;
|
|
2
|
+
//# sourceMappingURL=VirtualTable.module.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"VirtualTable.module.cjs","names":[],"sources":["../../../src/components/VirtualTable/VirtualTable.module.css"],"sourcesContent":[".scroll {\n width: 100%;\n overflow: auto;\n border: 1px solid var(--tempest-border);\n border-radius: var(--tempest-radius-lg);\n background-color: var(--tempest-bg);\n box-shadow: var(--tempest-shadow-xs);\n}\n\n.table {\n width: 100%;\n border-collapse: separate;\n border-spacing: 0;\n font-family: var(--tempest-font-sans);\n font-size: var(--tempest-text-base);\n line-height: var(--tempest-leading-snug);\n /*\n * Fixed layout is what keeps columns from jumping mid-scroll: with `auto`,\n * the browser sizes each column from the rows currently in the DOM, and a\n * virtualized table swaps those rows out as you scroll.\n */\n table-layout: fixed;\n}\n\n.caption {\n position: absolute;\n width: 1px;\n height: 1px;\n padding: 0;\n margin: -1px;\n overflow: hidden;\n clip-path: inset(50%);\n white-space: nowrap;\n border-width: 0;\n}\n\n/*\n * `border-collapse: separate` above exists for this: a sticky `<th>` inside a\n * collapsed table loses its bottom border while scrolling, because the shared\n * border belongs to the cell that scrolled away.\n */\n.head .th {\n position: sticky;\n top: 0;\n z-index: 1;\n}\n\n.th,\n.td {\n padding: 0 var(--tempest-space-4);\n text-align: left;\n border-bottom: 1px solid var(--tempest-border);\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.th {\n padding-block: var(--tempest-space-3);\n background-color: var(--tempest-surface);\n color: var(--tempest-text-muted);\n font-weight: var(--tempest-weight-semibold);\n font-size: var(--tempest-text-xs);\n letter-spacing: var(--tempest-tracking-wider);\n text-transform: uppercase;\n}\n\n.alignRight {\n text-align: right;\n}\n\n.alignCenter {\n text-align: center;\n}\n\n.sortButton {\n display: inline-flex;\n align-items: center;\n gap: var(--tempest-space-1);\n padding: 0;\n border: none;\n background: none;\n color: inherit;\n font: inherit;\n letter-spacing: inherit;\n text-transform: inherit;\n cursor: pointer;\n}\n\n.sortButton:focus-visible {\n outline: 2px solid var(--tempest-primary);\n outline-offset: 2px;\n border-radius: var(--tempest-radius-sm);\n}\n\n.sortIndicator {\n font-size: var(--tempest-text-xs);\n opacity: 0.55;\n}\n\n.tr.clickable {\n cursor: pointer;\n transition: background-color var(--tempest-duration-fast) var(--tempest-ease-out);\n}\n\n@media (hover: hover) and (pointer: fine) {\n .tr.clickable:hover {\n background-color: var(--tempest-surface);\n }\n}\n\n.tr.clickable:focus-visible {\n outline: 2px solid var(--tempest-primary);\n outline-offset: -2px;\n}\n\n.emptyRow {\n padding: var(--tempest-space-8) var(--tempest-space-4);\n text-align: center;\n color: var(--tempest-text-muted);\n}\n\n@media (prefers-reduced-motion: reduce) {\n .tr.clickable {\n transition: none;\n }\n}\n"],"mappings":""}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
//#region src/components/VirtualTable/VirtualTable.module.css
|
|
2
|
+
var e = "tempest_scroll_XOPRs", t = "tempest_table_wbJg-", n = "tempest_caption_Dt-O5", r = "tempest_head_9xVmx", i = "tempest_th_-xzNL", a = "tempest_td_Crp7i", o = "tempest_alignRight_uxhpx", s = "tempest_alignCenter_9B3Sb", c = "tempest_sortButton_4h-vK", l = "tempest_sortIndicator_-WpMp", u = "tempest_tr_EI3uW", d = "tempest_clickable_4AfSX", f = "tempest_emptyRow_4kIiT", p = {
|
|
3
|
+
scroll: e,
|
|
4
|
+
table: t,
|
|
5
|
+
caption: n,
|
|
6
|
+
head: r,
|
|
7
|
+
th: i,
|
|
8
|
+
td: a,
|
|
9
|
+
alignRight: o,
|
|
10
|
+
alignCenter: s,
|
|
11
|
+
sortButton: c,
|
|
12
|
+
sortIndicator: l,
|
|
13
|
+
tr: u,
|
|
14
|
+
clickable: d,
|
|
15
|
+
emptyRow: f
|
|
16
|
+
};
|
|
17
|
+
//#endregion
|
|
18
|
+
export { s as alignCenter, o as alignRight, n as caption, d as clickable, p as default, f as emptyRow, r as head, e as scroll, c as sortButton, l as sortIndicator, t as table, a as td, i as th, u as tr };
|
|
19
|
+
|
|
20
|
+
//# sourceMappingURL=VirtualTable.module.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"VirtualTable.module.js","names":[],"sources":["../../../src/components/VirtualTable/VirtualTable.module.css"],"sourcesContent":[".scroll {\n width: 100%;\n overflow: auto;\n border: 1px solid var(--tempest-border);\n border-radius: var(--tempest-radius-lg);\n background-color: var(--tempest-bg);\n box-shadow: var(--tempest-shadow-xs);\n}\n\n.table {\n width: 100%;\n border-collapse: separate;\n border-spacing: 0;\n font-family: var(--tempest-font-sans);\n font-size: var(--tempest-text-base);\n line-height: var(--tempest-leading-snug);\n /*\n * Fixed layout is what keeps columns from jumping mid-scroll: with `auto`,\n * the browser sizes each column from the rows currently in the DOM, and a\n * virtualized table swaps those rows out as you scroll.\n */\n table-layout: fixed;\n}\n\n.caption {\n position: absolute;\n width: 1px;\n height: 1px;\n padding: 0;\n margin: -1px;\n overflow: hidden;\n clip-path: inset(50%);\n white-space: nowrap;\n border-width: 0;\n}\n\n/*\n * `border-collapse: separate` above exists for this: a sticky `<th>` inside a\n * collapsed table loses its bottom border while scrolling, because the shared\n * border belongs to the cell that scrolled away.\n */\n.head .th {\n position: sticky;\n top: 0;\n z-index: 1;\n}\n\n.th,\n.td {\n padding: 0 var(--tempest-space-4);\n text-align: left;\n border-bottom: 1px solid var(--tempest-border);\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.th {\n padding-block: var(--tempest-space-3);\n background-color: var(--tempest-surface);\n color: var(--tempest-text-muted);\n font-weight: var(--tempest-weight-semibold);\n font-size: var(--tempest-text-xs);\n letter-spacing: var(--tempest-tracking-wider);\n text-transform: uppercase;\n}\n\n.alignRight {\n text-align: right;\n}\n\n.alignCenter {\n text-align: center;\n}\n\n.sortButton {\n display: inline-flex;\n align-items: center;\n gap: var(--tempest-space-1);\n padding: 0;\n border: none;\n background: none;\n color: inherit;\n font: inherit;\n letter-spacing: inherit;\n text-transform: inherit;\n cursor: pointer;\n}\n\n.sortButton:focus-visible {\n outline: 2px solid var(--tempest-primary);\n outline-offset: 2px;\n border-radius: var(--tempest-radius-sm);\n}\n\n.sortIndicator {\n font-size: var(--tempest-text-xs);\n opacity: 0.55;\n}\n\n.tr.clickable {\n cursor: pointer;\n transition: background-color var(--tempest-duration-fast) var(--tempest-ease-out);\n}\n\n@media (hover: hover) and (pointer: fine) {\n .tr.clickable:hover {\n background-color: var(--tempest-surface);\n }\n}\n\n.tr.clickable:focus-visible {\n outline: 2px solid var(--tempest-primary);\n outline-offset: -2px;\n}\n\n.emptyRow {\n padding: var(--tempest-space-8) var(--tempest-space-4);\n text-align: center;\n color: var(--tempest-text-muted);\n}\n\n@media (prefers-reduced-motion: reduce) {\n .tr.clickable {\n transition: none;\n }\n}\n"],"mappings":""}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
const e=require("../../utils/cn.cjs"),t=require("../Button/Button.cjs"),n=require("../Stepper/Stepper.cjs"),r=require("./Wizard.module.cjs");let i=require("react"),a=require("react/jsx-runtime");function o({steps:o,activeIndex:s,defaultActiveIndex:c=0,onStepChange:l,onComplete:u,nextLabel:d=`Next`,backLabel:f=`Back`,finishLabel:p=`Finish`,optionalLabel:m=`(optional)`,clickableSteps:h=!1,renderActions:g,className:_}){let v=s!==void 0,[y,b]=(0,i.useState)(c),[x,S]=(0,i.useState)(!1),C=Math.min(v?s:y,o.length-1),w=o[C],T=(0,i.useCallback)(e=>{v||b(e),l?.(e,o[e])},[v,l,o]),E=(0,i.useCallback)(async e=>{if(!e.validate)return!0;S(!0);try{return await e.validate()}catch{return!1}finally{S(!1)}},[]),D=(0,i.useCallback)(async()=>{if(await E(w)){if(C===o.length-1){await u?.();return}T(C+1)}},[C,T,u,E,w,o.length]),O=(0,i.useCallback)(()=>{C>0&&T(C-1)},[C,T]),k=(0,i.useCallback)(async e=>{let t=Math.max(0,Math.min(e,o.length-1));if(t!==C){if(t<C){T(t);return}for(let e=C;e<t;e+=1)if(!await E(o[e]))return;T(t)}},[C,T,E,o]),A=(0,i.useMemo)(()=>({activeIndex:C,step:w,validating:x,isFirst:C===0,isLast:C===o.length-1,next:D,back:O,goTo:k}),[O,C,k,D,w,o.length,x]),j=(0,i.useMemo)(()=>o.map(e=>({label:e.label,description:e.optional?`${e.description??``} ${m}`.trim():e.description})),[m,o]);return(0,a.jsxs)(`div`,{className:e.cn(r.default.wizard,_),children:[(0,a.jsx)(n.Stepper,{steps:j,current:C,onStepClick:h?e=>void k(e):void 0}),(0,a.jsx)(`div`,{className:r.default.body,role:`group`,"aria-label":w.label,children:typeof w.content==`function`?w.content(A):w.content}),g?g(A):(0,a.jsxs)(`div`,{className:r.default.actions,children:[(0,a.jsx)(t.Button,{variant:`secondary`,onClick:O,disabled:A.isFirst||x,children:f}),(0,a.jsx)(t.Button,{onClick:()=>void D(),loading:x,children:A.isLast?p:d})]})]})}exports.Wizard=o;
|
|
2
|
+
//# sourceMappingURL=Wizard.cjs.map
|