@datum-cloud/datum-ui 3.8.0 → 3.10.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/dist/autocomplete/index.mjs +1 -1
- package/dist/{autocomplete-D0zAcT78.mjs → autocomplete-CrCbO2VS.mjs} +10 -4
- package/dist/autosearch/index.mjs +1 -1
- package/dist/button-group/index.mjs +1 -1
- package/dist/{button-group-C3GKo-0p.mjs → button-group-DJ6X1SSj.mjs} +2 -2
- package/dist/{calendar-date-picker-CknZM6a2.mjs → calendar-date-picker-BRKs56gR.mjs} +1 -1
- package/dist/components/features/logs/hooks/use-logs-url-state.d.ts +59 -0
- package/dist/components/features/logs/index.d.ts +4 -1
- package/dist/components/features/logs/utils/facet-counts.d.ts +50 -0
- package/dist/components/features/logs/utils/facets.d.ts +2 -0
- package/dist/components/features/logs/utils/index.d.ts +4 -0
- package/dist/components/features/logs/utils/url-state.d.ts +61 -0
- package/dist/data-table/index.mjs +1 -1
- package/dist/{data-table-CpBwO8Ea.mjs → data-table-DFUnUydN.mjs} +5 -5
- package/dist/date-picker/index.mjs +3 -3
- package/dist/date-time-picker/index.mjs +1 -1
- package/dist/{date-time-picker-Bc41Ixrs.mjs → date-time-picker-BRMm2QSz.mjs} +1 -1
- package/dist/{date-time-range-picker-yy1Acntn.mjs → date-time-range-picker-CqGGJTLS.mjs} +18 -7
- package/dist/field-styles-D-FJatHt.mjs +31 -0
- package/dist/form/index.mjs +1 -1
- package/dist/{form-DTaVgDSV.mjs → form-VdbSqDjL.mjs} +5 -5
- package/dist/grouped-table/index.mjs +1 -1
- package/dist/{grouped-table-Dl6DclbV.mjs → grouped-table-B4HzLXq6.mjs} +1 -1
- package/dist/hooks/index.mjs +1 -1
- package/dist/hooks/use-breakpoint.d.ts +7 -2
- package/dist/index.mjs +19 -19
- package/dist/{layers-DLUbkJtt.mjs → layers-BC1Ny49w.mjs} +1 -1
- package/dist/logs/index.mjs +374 -80
- package/dist/map/index.mjs +1 -1
- package/dist/more-actions/index.mjs +1 -1
- package/dist/{more-actions-BlSOVwa8.mjs → more-actions-DXQiV-bN.mjs} +1 -1
- package/dist/multi-select/index.mjs +1 -1
- package/dist/{multi-select-C2cBrqXl.mjs → multi-select-DwcsJdHt.mjs} +32 -24
- package/dist/picker/index.mjs +2 -2
- package/dist/{picker-DC3GErYg.mjs → picker-BHPtncpv.mjs} +2 -2
- package/dist/responsive-dropdown/index.mjs +1 -1
- package/dist/{responsive-dropdown-DsWgpE_i.mjs → responsive-dropdown-B9cDUeHt.mjs} +1 -1
- package/dist/responsive-popover/index.mjs +1 -1
- package/dist/{responsive-popover-DJYd8lOK.mjs → responsive-popover-B_pUxrZ1.mjs} +1 -1
- package/dist/rich-text-editor/index.mjs +1 -1
- package/dist/{rich-text-editor-BUz06s-b.mjs → rich-text-editor-CPd_6vdZ.mjs} +1 -1
- package/dist/select/index.mjs +1 -1
- package/dist/{select-DemYhwnG.mjs → select-B0Xlz-wD.mjs} +3 -2
- package/dist/{select-jgK6wyXj.mjs → select-CGsHf70u.mjs} +7 -2
- package/dist/task-queue/index.mjs +1 -1
- package/dist/{task-queue-dropdown-DuCAAybs.mjs → task-queue-dropdown-BflEFiMi.mjs} +1 -1
- package/dist/time-picker/index.mjs +1 -1
- package/dist/{time-picker-B_am4eAK.mjs → time-picker-BFwH-Vd3.mjs} +1 -1
- package/dist/{to-api-format-DyImCzCn.mjs → to-api-format-BiWOTFha.mjs} +3 -3
- package/dist/{use-breakpoint-zY_JYINK.mjs → use-breakpoint-Ce5tS4cU.mjs} +11 -5
- package/dist/utils/field-styles.d.ts +21 -0
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -7,7 +7,7 @@ import { t as SpinnerIcon } from "./spinner.icon-BiUnMAxw.mjs";
|
|
|
7
7
|
import { n as buttonVariants, t as Button } from "./button-Cn4KagBO.mjs";
|
|
8
8
|
import { t as LinkButton } from "./button-IK-Lnu_9.mjs";
|
|
9
9
|
import { t as Separator } from "./separator-DNiiN2BN.mjs";
|
|
10
|
-
import { i as buttonGroupVariants, n as ButtonGroupSeparator, r as ButtonGroupText, t as ButtonGroup } from "./button-group-
|
|
10
|
+
import { i as buttonGroupVariants, n as ButtonGroupSeparator, r as ButtonGroupText, t as ButtonGroup } from "./button-group-DJ6X1SSj.mjs";
|
|
11
11
|
import { t as Icon } from "./icon-wrapper-CIk2th6R.mjs";
|
|
12
12
|
import { Calendar, CalendarDayButton } from "./calendar/index.mjs";
|
|
13
13
|
import { a as CardField, c as CardFooter, d as CardTitle, i as CardContent, l as CardHeader, n as Card, o as CardFieldLabel, r as CardAction, s as CardFieldValue, t as CardSaveBar, u as CardDescription } from "./card-save-bar-Te8jf-ie.mjs";
|
|
@@ -23,16 +23,16 @@ import { n as HoverCardContent, r as HoverCardTrigger, t as HoverCard } from "./
|
|
|
23
23
|
import { t as Input } from "./input-DsT5qkJn.mjs";
|
|
24
24
|
import { a as InputGroupText, i as InputGroupInput, n as InputGroupAddon, o as InputGroupTextarea, r as InputGroupButton, t as InputGroup } from "./input-group-CCzvJIZM.mjs";
|
|
25
25
|
import { t as Label } from "./label-BR1V3Imy.mjs";
|
|
26
|
-
import { A as useLeaflet, C as MapMarkerClusterGroup, D as MapRectangle, E as MapPopup, O as MapTooltip, S as MapMarker, T as MapPolyline, _ as MapLocateControl, a as MapTileLayer, b as MapCircle, c as MapDrawDelete, d as MapDrawPolygon, f as MapDrawPolyline, g as MapFullscreenControl, h as MapControlContainer, i as MapLayersControl, j as PlaceAutocomplete, k as Map, l as MapDrawEdit, m as MapDrawUndo, n as MapLayerGroup, o as MapDrawCircle, p as MapDrawRectangle, r as MapLayers, s as MapDrawControl, t as MapFeatureGroup, u as MapDrawMarker, v as MapSearchControl, w as MapPolygon, x as MapCircleMarker, y as MapZoomControl } from "./layers-
|
|
26
|
+
import { A as useLeaflet, C as MapMarkerClusterGroup, D as MapRectangle, E as MapPopup, O as MapTooltip, S as MapMarker, T as MapPolyline, _ as MapLocateControl, a as MapTileLayer, b as MapCircle, c as MapDrawDelete, d as MapDrawPolygon, f as MapDrawPolyline, g as MapFullscreenControl, h as MapControlContainer, i as MapLayersControl, j as PlaceAutocomplete, k as Map, l as MapDrawEdit, m as MapDrawUndo, n as MapLayerGroup, o as MapDrawCircle, p as MapDrawRectangle, r as MapLayers, s as MapDrawControl, t as MapFeatureGroup, u as MapDrawMarker, v as MapSearchControl, w as MapPolygon, x as MapCircleMarker, y as MapZoomControl } from "./layers-BC1Ny49w.mjs";
|
|
27
27
|
import { i as useInSheet, n as MobileSheet, r as InSheetContext, t as ResponsiveSheetTrigger } from "./mobile-sheet-1995HYY_.mjs";
|
|
28
28
|
import { a as SheetHeader, i as SheetFooter, o as SheetTitle, r as SheetDescription, s as SheetTrigger } from "./sheet-DYPtVIb2.mjs";
|
|
29
29
|
import { i as SheetOverlay, n as SheetClose, r as SheetContent, t as Sheet } from "./sheet-DEpEJ_Rk.mjs";
|
|
30
30
|
import { i as PopoverTrigger, n as PopoverAnchor, r as PopoverContent, t as Popover } from "./popover-7YxyP_W0.mjs";
|
|
31
31
|
import { n as RadioGroupItem, t as RadioGroup } from "./radio-group-Boxi2hm0.mjs";
|
|
32
|
-
import { t as useBreakpoint } from "./use-breakpoint-
|
|
33
|
-
import { t as ResponsiveDropdown } from "./responsive-dropdown-
|
|
34
|
-
import { t as ResponsivePopover } from "./responsive-popover-
|
|
35
|
-
import { a as SelectLabel, c as SelectSeparator, i as SelectItem, l as SelectTrigger, n as SelectContent, o as SelectScrollDownButton, r as SelectGroup, s as SelectScrollUpButton, t as Select, u as SelectValue } from "./select-
|
|
32
|
+
import { t as useBreakpoint } from "./use-breakpoint-Ce5tS4cU.mjs";
|
|
33
|
+
import { t as ResponsiveDropdown } from "./responsive-dropdown-B9cDUeHt.mjs";
|
|
34
|
+
import { t as ResponsivePopover } from "./responsive-popover-B_pUxrZ1.mjs";
|
|
35
|
+
import { a as SelectLabel, c as SelectSeparator, i as SelectItem, l as SelectTrigger, n as SelectContent, o as SelectScrollDownButton, r as SelectGroup, s as SelectScrollUpButton, t as Select, u as SelectValue } from "./select-B0Xlz-wD.mjs";
|
|
36
36
|
import { n as SettingsNavItem, r as SettingsNavLabel, t as SettingsNav } from "./settings-nav-CCZdPD-x.mjs";
|
|
37
37
|
import { C as SidebarProvider, S as SidebarGroupLabel, _ as SidebarMenuSubButton, a as SidebarInput, b as SidebarGroupAction, c as SidebarSeparator, d as SidebarMenuAction, f as SidebarMenuBadge, g as SidebarMenuSub, h as SidebarMenuSkeleton, i as SidebarHeader, l as SidebarTrigger, m as SidebarMenuItem, n as SidebarContent, o as SidebarInset, p as SidebarMenuButton, r as SidebarFooter, s as SidebarRail, t as Sidebar, u as SidebarMenu, v as SidebarMenuSubItem, w as useSidebar, x as SidebarGroupContent, y as SidebarGroup } from "./sidebar-DWnxQWQ8.mjs";
|
|
38
38
|
import { t as Tooltip } from "./tooltip-OIySjJWW.mjs";
|
|
@@ -46,44 +46,44 @@ import { a as ListItem, c as Title, d as titleVariants, i as List, l as paragrap
|
|
|
46
46
|
import { t as VisuallyHidden } from "./visuallyhidden-Mg4OsZ-l.mjs";
|
|
47
47
|
import { a as hasActiveDescendant, i as findItemByHref, n as NavMenu, o as isNavItemActive, r as NavMenuItem, s as normalizePath, t as AppNavigation } from "./app-navigation-DyNZwlSG.mjs";
|
|
48
48
|
import { t as LoaderOverlay } from "./loader-overlay-DP0pvHuG.mjs";
|
|
49
|
-
import { t as Autocomplete } from "./autocomplete-
|
|
49
|
+
import { t as Autocomplete } from "./autocomplete-CrCbO2VS.mjs";
|
|
50
50
|
import { Autosearch, defaultAutosearchValue } from "./autosearch/index.mjs";
|
|
51
51
|
import { n as avatarStackVariants, t as AvatarStack } from "./avatar-stack-2ow672bR.mjs";
|
|
52
|
-
import { M as getBrowserTimezone, N as getTimezoneOffset, j as formatTimezoneLabel } from "./date-time-range-picker-
|
|
53
|
-
import { t as CalendarDatePicker } from "./calendar-date-picker-
|
|
52
|
+
import { M as getBrowserTimezone, N as getTimezoneOffset, j as formatTimezoneLabel } from "./date-time-range-picker-CqGGJTLS.mjs";
|
|
53
|
+
import { t as CalendarDatePicker } from "./calendar-date-picker-BRKs56gR.mjs";
|
|
54
54
|
import { i as ClientOnly, n as useTheme, r as ThemeScript, t as ThemeProvider } from "./themes-BoxnQbbu.mjs";
|
|
55
55
|
import { a as formatJson, c as isValidYaml, d as CodeEditor, i as CodeEditorTabs, l as jsonToYaml, n as jsonSchema, o as formatYaml, r as yamlSchema, s as isValidJson, t as createCodeEditorSchema, u as yamlToJson } from "./types-ChINrR8H.mjs";
|
|
56
56
|
import { t as toast } from "./toast-CizxCEcK.mjs";
|
|
57
57
|
import { n as Toaster, t as useToast } from "./use-toast-CZAZeS95.mjs";
|
|
58
|
-
import { _ as useNuqsAdapter, a as useDataTablePagination, b as DEFAULT_PAGE_SIZE, c as useDataTableSelection, d as resolvePath, f as rowMatchesSearch, g as createSelectionColumn, h as DataTableColumnHeader, i as useDataTableLoading, l as useDataTableSorting, m as DataTableRowActions, n as useDataTableFilters, o as useDataTableRows, p as dataTableFeatures, r as useDataTableInlineContents, s as useDataTableSearch, t as DataTable, u as createDataTableStore, v as DEFAULT_DEBOUNCE_MS, x as DEFAULT_PAGE_SIZES, y as DEFAULT_LOADING_ROWS } from "./data-table-
|
|
58
|
+
import { _ as useNuqsAdapter, a as useDataTablePagination, b as DEFAULT_PAGE_SIZE, c as useDataTableSelection, d as resolvePath, f as rowMatchesSearch, g as createSelectionColumn, h as DataTableColumnHeader, i as useDataTableLoading, l as useDataTableSorting, m as DataTableRowActions, n as useDataTableFilters, o as useDataTableRows, p as dataTableFeatures, r as useDataTableInlineContents, s as useDataTableSearch, t as DataTable, u as createDataTableStore, v as DEFAULT_DEBOUNCE_MS, x as DEFAULT_PAGE_SIZES, y as DEFAULT_LOADING_ROWS } from "./data-table-DFUnUydN.mjs";
|
|
59
59
|
import { t as ActionRow } from "./action-row-BEzE9x37.mjs";
|
|
60
60
|
import { n as useDebouncedSearchInput, t as DEFAULT_SEARCH_DEBOUNCE_MS } from "./use-debounced-search-input-B4u28iLx.mjs";
|
|
61
|
-
import { t as MultiSelect } from "./multi-select-
|
|
61
|
+
import { t as MultiSelect } from "./multi-select-DwcsJdHt.mjs";
|
|
62
62
|
import { a as formatRelativeDate, d as parseDate, i as formatCombinedDate, l as getTimestamp, n as DEFAULT_DATE_FORMAT, o as formatTimezoneDate, r as formatAbsoluteDate, s as formatUTCDate, t as DateTime, u as getTimezoneAbbreviation } from "./date-time-BBRVM9qb.mjs";
|
|
63
|
-
import { t as DateTimePicker } from "./date-time-picker-
|
|
63
|
+
import { t as DateTimePicker } from "./date-time-picker-BRMm2QSz.mjs";
|
|
64
64
|
import { a as DropdownMenuItem, c as DropdownMenuRadioGroup, d as DropdownMenuShortcut, f as DropdownMenuSub, h as DropdownMenuTrigger, i as DropdownMenuGroup, l as DropdownMenuRadioItem, m as DropdownMenuSubTrigger, n as DropdownMenuCheckboxItem, o as DropdownMenuLabel, p as DropdownMenuSubContent, r as DropdownMenuContent, s as DropdownMenuPortal, t as DropdownMenu, u as DropdownMenuSeparator } from "./dropdown-DR9j3Ni_.mjs";
|
|
65
65
|
import { i as FileInputButton, n as DropzoneContent, r as DropzoneEmptyState, t as Dropzone } from "./dropzone-qKYfSe7o.mjs";
|
|
66
66
|
import { t as EmptyContent } from "./empty-content-CTMHak36.mjs";
|
|
67
|
-
import { A as FormCheckbox, C as FormDialog, D as FormCustom, E as FormDatePicker, M as FormAutosearch, N as FormAutocomplete, O as FormCopyBox, S as FormError, T as FormDateTimePicker, _ as FormRadioGroup, a as useField, b as FormFieldArray, c as useWatchAll, d as FormTextarea, f as FormSwitch, g as FormRoot, h as FormSelectItem, i as useFieldContext, j as FormButton, k as FormCombobox, l as FormTransfer, m as FormSelect, n as useFormState, o as FormWhen, p as FormSubmit, r as useFormContext, s as useWatch, t as Form, u as FormTimePicker, v as FormRadioItem, w as FormDescription, x as FormField, y as FormInput } from "./form-
|
|
67
|
+
import { A as FormCheckbox, C as FormDialog, D as FormCustom, E as FormDatePicker, M as FormAutosearch, N as FormAutocomplete, O as FormCopyBox, S as FormError, T as FormDateTimePicker, _ as FormRadioGroup, a as useField, b as FormFieldArray, c as useWatchAll, d as FormTextarea, f as FormSwitch, g as FormRoot, h as FormSelectItem, i as useFieldContext, j as FormButton, k as FormCombobox, l as FormTransfer, m as FormSelect, n as useFormState, o as FormWhen, p as FormSubmit, r as useFormContext, s as useWatch, t as Form, u as FormTimePicker, v as FormRadioItem, w as FormDescription, x as FormField, y as FormInput } from "./form-VdbSqDjL.mjs";
|
|
68
68
|
import { t as useCopyToClipboard } from "./use-copy-to-clipboard-CWKWHLxI.mjs";
|
|
69
69
|
import { n as useAdapter, t as FormAdapterProvider } from "./adapter-context-XT749tyT.mjs";
|
|
70
70
|
import { InputWithAddons } from "./input-with-addons/index.mjs";
|
|
71
|
-
import { t as TimePicker } from "./time-picker-
|
|
71
|
+
import { t as TimePicker } from "./time-picker-BFwH-Vd3.mjs";
|
|
72
72
|
import { t as Transfer } from "./transfer-DGUeAQUL.mjs";
|
|
73
73
|
import { a as getResponsiveValue, c as GRID_COLUMNS, d as RESPONSIVE_MAP, i as getGutter, l as GRID_PREFIX, n as Row, o as registerMediaQuery, r as RowContext, s as GRID_BREAKPOINTS, t as Col, u as RESPONSIVE_ARRAY } from "./col-CYHIfPJq.mjs";
|
|
74
|
-
import { t as GroupedTable } from "./grouped-table-
|
|
74
|
+
import { t as GroupedTable } from "./grouped-table-B4HzLXq6.mjs";
|
|
75
75
|
import { t as InputNumber } from "./input-number-DF-bfIo8.mjs";
|
|
76
76
|
import { a as logoStyles, i as LogoFlat, n as LogoStacked, r as LogoIcon, t as LogoText } from "./logo-text-B54YiEte.mjs";
|
|
77
77
|
import { t as Logo } from "./logo-CkzKra6H.mjs";
|
|
78
|
-
import { t as MoreActions } from "./more-actions-
|
|
78
|
+
import { t as MoreActions } from "./more-actions-DXQiV-bN.mjs";
|
|
79
79
|
import { configureProgress, startProgress, stopProgress } from "./nprogress/index.mjs";
|
|
80
80
|
import { t as PageTitle } from "./page-title-Djl3LvPT.mjs";
|
|
81
81
|
import { t as RichTextContent } from "./rich-text-content-BiIIowBU.mjs";
|
|
82
|
-
import { n as useRichTextEditor, t as RichTextEditor } from "./rich-text-editor-
|
|
82
|
+
import { n as useRichTextEditor, t as RichTextEditor } from "./rich-text-editor-CPd_6vdZ.mjs";
|
|
83
83
|
import { t as defineStepper } from "./stepper-ZipxpzWY.mjs";
|
|
84
84
|
import { t as TagsInput } from "./tag-input-a3ktkGrH.mjs";
|
|
85
|
-
import { _ as RedisTaskStorage, a as TaskPanelItem, b as createProjectMetadata, c as TaskPanelHeader, d as useCurrentScope, f as useTasksWithLabels, g as detectStorage, h as TaskQueue, i as TaskPanel, l as getContextLabel, m as TaskQueueProvider, n as TaskSummaryDialog, o as TaskPanelCounter, p as useTaskQueue, r as TaskQueueTrigger, s as TaskPanelActions, t as TaskQueueDropdown, u as matchesCurrentScope, v as LocalTaskStorage, x as createUserMetadata, y as createOrgMetadata } from "./task-queue-dropdown-
|
|
86
|
-
import { _ as getShortTimezoneDisplay, a as TimeRangePicker, b as utcToLocalInputString, c as getPresetByKey, d as TimezoneSelector, f as QuickRangesPanel, g as getDefaultTimezoneOptions, h as formatUtcForDisplay, i as formatTimeRangeDisplay, l as getPresetByShortcut, m as createTimezoneOption, n as formatDateForInput, o as DEFAULT_PRESETS, p as CustomRangePanel, r as formatSingleTimeDisplay, s as getDefaultPreset, t as toApiTimeRange, u as getPresetRange, v as localInputStringToUtc, x as zonedDateToUtcString, y as utcStringToZonedDate } from "./to-api-format-
|
|
85
|
+
import { _ as RedisTaskStorage, a as TaskPanelItem, b as createProjectMetadata, c as TaskPanelHeader, d as useCurrentScope, f as useTasksWithLabels, g as detectStorage, h as TaskQueue, i as TaskPanel, l as getContextLabel, m as TaskQueueProvider, n as TaskSummaryDialog, o as TaskPanelCounter, p as useTaskQueue, r as TaskQueueTrigger, s as TaskPanelActions, t as TaskQueueDropdown, u as matchesCurrentScope, v as LocalTaskStorage, x as createUserMetadata, y as createOrgMetadata } from "./task-queue-dropdown-BflEFiMi.mjs";
|
|
86
|
+
import { _ as getShortTimezoneDisplay, a as TimeRangePicker, b as utcToLocalInputString, c as getPresetByKey, d as TimezoneSelector, f as QuickRangesPanel, g as getDefaultTimezoneOptions, h as formatUtcForDisplay, i as formatTimeRangeDisplay, l as getPresetByShortcut, m as createTimezoneOption, n as formatDateForInput, o as DEFAULT_PRESETS, p as CustomRangePanel, r as formatSingleTimeDisplay, s as getDefaultPreset, t as toApiTimeRange, u as getPresetRange, v as localInputStringToUtc, x as zonedDateToUtcString, y as utcStringToZonedDate } from "./to-api-format-BiWOTFha.mjs";
|
|
87
87
|
import { t as useDebounce } from "./hooks-WVJbyhCz.mjs";
|
|
88
88
|
import { n as toUTCTimestampStartOfDay, t as toUTCTimestampEndOfDay } from "./utils-CPJ5MCfd.mjs";
|
|
89
89
|
export { CustomRangePanel as AbsoluteRangePanel, CustomRangePanel, ActionRow, Alert, AlertDescription, AlertTitle, AppNavigation, Autocomplete, Autosearch, Avatar, AvatarFallback, AvatarImage, AvatarStack, Badge, Blockquote, Breadcrumb, BreadcrumbEllipsis, BreadcrumbItem, BreadcrumbLink, BreadcrumbList, BreadcrumbPage, BreadcrumbSeparator, Button, ButtonGroup, ButtonGroupSeparator, ButtonGroupText, Calendar, CalendarDatePicker, CalendarDayButton, Card, CardAction, CardContent, CardDescription, CardField, CardFieldLabel, CardFieldValue, CardFooter, CardHeader, CardSaveBar, CardTitle, ChartContainer, ChartLegend, ChartLegendContent, ChartStyle, ChartTooltip, ChartTooltipContent, Checkbox, ClientOnly, CloseIcon, Code, CodeEditor, CodeEditorTabs, Col, Collapsible, CollapsibleContent, CollapsibleTrigger, Command, CommandDialog, CommandEmpty, CommandGroup, CommandInput, CommandItem, CommandList, CommandSeparator, CommandShortcut, DEFAULT_DATE_FORMAT, DEFAULT_DEBOUNCE_MS, DEFAULT_LOADING_ROWS, DEFAULT_PAGE_SIZE, DEFAULT_PAGE_SIZES, DEFAULT_PRESETS, DEFAULT_SEARCH_DEBOUNCE_MS, DURATION, DataTable, DataTableColumnHeader, DataTableRowActions, DateTime, DateTimePicker, Dialog, DropdownMenu, DropdownMenuCheckboxItem, DropdownMenuContent, DropdownMenuGroup, DropdownMenuItem, DropdownMenuLabel, DropdownMenuPortal, DropdownMenuRadioGroup, DropdownMenuRadioItem, DropdownMenuSeparator, DropdownMenuShortcut, DropdownMenuSub, DropdownMenuSubContent, DropdownMenuSubTrigger, DropdownMenuTrigger, Dropzone, DropzoneContent, DropzoneEmptyState, EASE, EmptyContent, FileInputButton, Form, FormAdapterProvider, FormAutocomplete, FormAutosearch, FormButton, FormCheckbox, FormCombobox, FormCopyBox, FormCustom, FormDatePicker, FormDateTimePicker, FormDescription, FormDialog, FormError, FormField, FormFieldArray, FormInput, FormRadioGroup, FormRadioItem, FormRoot, FormSelect, FormSelectItem, FormSubmit, FormSwitch, FormTextarea, FormTimePicker, FormTransfer, FormWhen, GRID_BREAKPOINTS, GRID_COLUMNS, GRID_PREFIX, GroupedTable, HoverCard, HoverCardContent, HoverCardTrigger, Icon, InSheetContext, Input, InputGroup, InputGroupAddon, InputGroupButton, InputGroupInput, InputGroupText, InputGroupTextarea, InputNumber, InputWithAddons, Label, Link, LinkButton, List, ListItem, LoaderOverlay, LocalTaskStorage, Logo, LogoFlat, LogoIcon, LogoStacked, LogoText, Map, MapCircle, MapCircleMarker, MapControlContainer, MapDrawCircle, MapDrawControl, MapDrawDelete, MapDrawEdit, MapDrawMarker, MapDrawPolygon, MapDrawPolyline, MapDrawRectangle, MapDrawUndo, MapFeatureGroup, MapFullscreenControl, MapLayerGroup, MapLayers, MapLayersControl, MapLocateControl, MapMarker, MapMarkerClusterGroup, MapPolygon, MapPolyline, MapPopup, MapRectangle, MapSearchControl, MapTileLayer, MapTooltip, MapZoomControl, MobileSheet, MoreActions, MultiSelect, NavMenu, NavMenuItem, PageTitle, Paragraph, PlaceAutocomplete, Popover, PopoverAnchor, PopoverContent, PopoverTrigger, QuickRangesPanel, RESPONSIVE_ARRAY, RESPONSIVE_MAP, RadioGroup, RadioGroupItem, RedisTaskStorage, ResponsiveDropdown, ResponsivePopover, ResponsiveSheetTrigger, RichTextContent, RichTextEditor, Row, RowContext, Select, SelectContent, SelectGroup, SelectItem, SelectLabel, SelectScrollDownButton, SelectScrollUpButton, SelectSeparator, SelectTrigger, SelectValue, Separator, SettingsNav, SettingsNavItem, SettingsNavLabel, Sheet, SheetClose, SheetContent, SheetDescription, SheetFooter, SheetHeader, SheetOverlay, SheetTitle, SheetTrigger, Sidebar, SidebarContent, SidebarFooter, SidebarGroup, SidebarGroupAction, SidebarGroupContent, SidebarGroupLabel, SidebarHeader, SidebarInput, SidebarInset, SidebarMenu, SidebarMenuAction, SidebarMenuBadge, SidebarMenuButton, SidebarMenuItem, SidebarMenuSkeleton, SidebarMenuSub, SidebarMenuSubButton, SidebarMenuSubItem, SidebarProvider, SidebarRail, SidebarSeparator, SidebarTrigger, Skeleton, Spinner, SpinnerIcon, Switch, Table, TableBody, TableCaption, TableCell, TableFooter, TableHead, TableHeader, TableRow, Tabs, TabsContent, TabsLinkTrigger, TabsList, TabsTrigger, TagsInput, TaskPanel, TaskPanelActions, TaskPanelCounter, TaskPanelHeader, TaskPanelItem, TaskQueue, TaskQueueDropdown, TaskQueueProvider, TaskQueueTrigger, TaskSummaryDialog, Text, Textarea, ThemeProvider, ThemeScript, TimePicker, TimeRangePicker, TimezoneSelector, Title, Toaster, Tooltip, Transfer, VisuallyHidden, avatarStackVariants, badgeVariants, buttonGroupVariants, buttonVariants, cn, configureProgress, createCodeEditorSchema, createDataTableStore, createOrgMetadata, createProjectMetadata, createSelectionColumn, createTimezoneOption, createUserMetadata, dataTableFeatures, defaultAutosearchValue, defineStepper, detectStorage, findItemByHref, formatAbsoluteDate, formatCombinedDate, formatDateForInput, formatJson, formatRelativeDate, formatSingleTimeDisplay, formatTimeRangeDisplay, formatTimezoneDate, formatTimezoneLabel, formatUTCDate, formatUtcForDisplay, formatYaml, getBrowserTimezone, getContextLabel, getDefaultPreset, getDefaultTimezoneOptions, getGutter, getPresetByKey, getPresetByShortcut, getPresetRange, getResponsiveValue, getShortTimezoneDisplay, getTimestamp, getTimezoneAbbreviation, getTimezoneOffset, hasActiveDescendant, isNavItemActive, isValidJson, isValidYaml, jsonSchema, jsonToYaml, localInputStringToUtc, logoStyles, matchesCurrentScope, normalizePath, paragraphVariants, parseDate, registerMediaQuery, resolvePath, rowMatchesSearch, startProgress, stopProgress, textVariants, titleVariants, toApiTimeRange, toUTCTimestampEndOfDay, toUTCTimestampStartOfDay, toast, useAdapter, useBreakpoint, useControllableState, useCopyToClipboard, useCurrentScope, useDataTableFilters, useDataTableInlineContents, useDataTableLoading, useDataTablePagination, useDataTableRows, useDataTableSearch, useDataTableSelection, useDataTableSorting, useDebounce, useDebouncedSearchInput, useField, useFieldContext, useFormContext, useFormState, useInSheet, useLeaflet, useNuqsAdapter, useRichTextEditor, useSidebar, useTaskQueue, useTasksWithLabels, useTheme, useToast, useWatch, useWatchAll, utcStringToZonedDate, utcToLocalInputString, yamlSchema, yamlToJson, zonedDateToUtcString };
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { t as cn } from "./utils-CTIuhCOs.mjs";
|
|
2
|
-
import { t as ButtonGroup } from "./button-group-
|
|
2
|
+
import { t as ButtonGroup } from "./button-group-DJ6X1SSj.mjs";
|
|
3
3
|
import { t as Button } from "./button-C57mkFkS.mjs";
|
|
4
4
|
import { i as CommandGroup, o as CommandItem, r as CommandEmpty, s as CommandList, t as Command } from "./command-B0be-zU5.mjs";
|
|
5
5
|
import { i as InputGroupInput, n as InputGroupAddon, t as InputGroup } from "./input-group-CCzvJIZM.mjs";
|
package/dist/logs/index.mjs
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { t as cn } from "../utils-CTIuhCOs.mjs";
|
|
2
2
|
import { Skeleton } from "../skeleton/index.mjs";
|
|
3
3
|
import { Badge } from "../badge/index.mjs";
|
|
4
|
-
import { t as useBreakpoint } from "../use-breakpoint-
|
|
4
|
+
import { t as useBreakpoint } from "../use-breakpoint-Ce5tS4cU.mjs";
|
|
5
5
|
import { t as useCopyToClipboard } from "../use-copy-to-clipboard-CWKWHLxI.mjs";
|
|
6
6
|
import { t as Button } from "../button-Cn4KagBO.mjs";
|
|
7
7
|
import { t as Sheet } from "../sheet-DEpEJ_Rk.mjs";
|
|
@@ -10,11 +10,11 @@ import { t as CopyStateIcon } from "../copy-state-icon-DMvXXsZm.mjs";
|
|
|
10
10
|
import { c as getBrowserTimezone, t as DateTime, u as getTimezoneAbbreviation } from "../date-time-BBRVM9qb.mjs";
|
|
11
11
|
import { t as Checkbox } from "../checkbox-BAo5sbHk.mjs";
|
|
12
12
|
import { n as CollapsibleContent, r as CollapsibleTrigger, t as Collapsible } from "../collapsible-B-KP3JZ-.mjs";
|
|
13
|
-
import { t as DateTimeRangePicker } from "../date-time-range-picker-
|
|
13
|
+
import { t as DateTimeRangePicker } from "../date-time-range-picker-CqGGJTLS.mjs";
|
|
14
14
|
import { TableBody, TableCell, TableHead, TableHeader, TableRow } from "../table/index.mjs";
|
|
15
15
|
import { t as Input } from "../input-DsT5qkJn.mjs";
|
|
16
16
|
import { Bot, ChevronDown, ChevronUp, Clock, Download, HelpCircle, Inbox, Monitor, RefreshCw, Search, SlidersHorizontal, Smartphone, Tablet, TriangleAlert, X } from "lucide-react";
|
|
17
|
-
import { createContext, memo, use, useCallback, useEffect, useMemo, useRef, useState } from "react";
|
|
17
|
+
import { createContext, memo, use, useCallback, useEffect, useMemo, useRef, useState, useSyncExternalStore } from "react";
|
|
18
18
|
import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
|
|
19
19
|
import { AnimatePresence, motion, useReducedMotion } from "motion/react";
|
|
20
20
|
import { format, isSameDay } from "date-fns";
|
|
@@ -320,6 +320,322 @@ function useLogs() {
|
|
|
320
320
|
if (!context) throw new Error("Logs components must be used within <Logs.Root>");
|
|
321
321
|
return context;
|
|
322
322
|
}
|
|
323
|
+
// src/components/features/logs/utils/time-range.ts
|
|
324
|
+
const MINUTE_MS$1 = 6e4;
|
|
325
|
+
const HOUR_MS = 60 * MINUTE_MS$1;
|
|
326
|
+
const DAY_MS$1 = 24 * HOUR_MS;
|
|
327
|
+
function relativePreset(key, label, durationMs, shortcut) {
|
|
328
|
+
return {
|
|
329
|
+
key,
|
|
330
|
+
label,
|
|
331
|
+
shortcut,
|
|
332
|
+
getRange: () => {
|
|
333
|
+
const now = /* @__PURE__ */ new Date();
|
|
334
|
+
return {
|
|
335
|
+
from: new Date(now.getTime() - durationMs),
|
|
336
|
+
to: now
|
|
337
|
+
};
|
|
338
|
+
}
|
|
339
|
+
};
|
|
340
|
+
}
|
|
341
|
+
/**
|
|
342
|
+
* Relative "Last N" windows offered by `Logs.Filters`. Keys are persisted on
|
|
343
|
+
* `LogTimeRange.preset` so hosts can slide the window forward with
|
|
344
|
+
* `resolveLogTimeRange` on refresh or while live tailing.
|
|
345
|
+
*
|
|
346
|
+
* Shortcuts follow the `picker` datetime presets (`1` / `2` / `H` / `W`) that
|
|
347
|
+
* the logs picker is built on. Keys that mean something else in the pickers
|
|
348
|
+
* (`3` is "Last 30 minutes" in `time-range-picker`, `D` is "Today") are not
|
|
349
|
+
* reused, so muscle memory carries over between the two.
|
|
350
|
+
*/
|
|
351
|
+
const LOG_TIME_PRESETS = [
|
|
352
|
+
relativePreset("last-15m", "Last 15 minutes", 15 * MINUTE_MS$1, "1"),
|
|
353
|
+
relativePreset("last-30m", "Last 30 minutes", 30 * MINUTE_MS$1, "2"),
|
|
354
|
+
relativePreset("last-1h", "Last hour", HOUR_MS, "H"),
|
|
355
|
+
relativePreset("last-3h", "Last 3 hours", 3 * HOUR_MS),
|
|
356
|
+
relativePreset("last-6h", "Last 6 hours", 6 * HOUR_MS, "6"),
|
|
357
|
+
relativePreset("last-12h", "Last 12 hours", 12 * HOUR_MS),
|
|
358
|
+
relativePreset("last-24h", "Last 24 hours", DAY_MS$1),
|
|
359
|
+
relativePreset("last-7d", "Last 7 days", 7 * DAY_MS$1, "W")
|
|
360
|
+
];
|
|
361
|
+
function lastThirtyMinutes(now = /* @__PURE__ */ new Date()) {
|
|
362
|
+
return {
|
|
363
|
+
from: (/* @__PURE__ */ new Date(now.getTime() - 30 * MINUTE_MS$1)).toISOString(),
|
|
364
|
+
to: now.toISOString(),
|
|
365
|
+
preset: "last-30m"
|
|
366
|
+
};
|
|
367
|
+
}
|
|
368
|
+
/**
|
|
369
|
+
* Re-anchor a preset range to `now`. Absolute ranges (no `preset`, or an
|
|
370
|
+
* unknown key) are returned unchanged.
|
|
371
|
+
*/
|
|
372
|
+
function resolveLogTimeRange(range, now = /* @__PURE__ */ new Date()) {
|
|
373
|
+
if (!range.preset) return range;
|
|
374
|
+
const preset = LOG_TIME_PRESETS.find((item) => item.key === range.preset);
|
|
375
|
+
if (!preset) return range;
|
|
376
|
+
const { from, to } = preset.getRange("UTC");
|
|
377
|
+
const shift = now.getTime() - to.getTime();
|
|
378
|
+
return {
|
|
379
|
+
from: new Date(from.getTime() + shift).toISOString(),
|
|
380
|
+
to: now.toISOString(),
|
|
381
|
+
preset: range.preset
|
|
382
|
+
};
|
|
383
|
+
}
|
|
384
|
+
/** Human label for the time-range trigger: preset name, or a compact absolute range. */
|
|
385
|
+
function logTimeRangeLabel(range) {
|
|
386
|
+
const preset = range.preset ? LOG_TIME_PRESETS.find((item) => item.key === range.preset) : void 0;
|
|
387
|
+
if (preset) return preset.label;
|
|
388
|
+
const from = new Date(range.from);
|
|
389
|
+
const to = new Date(range.to);
|
|
390
|
+
if (Number.isNaN(from.getTime()) || Number.isNaN(to.getTime())) return "Select range";
|
|
391
|
+
if (isSameDay(from, to)) return `${format(from, "MMM d, HH:mm")} – ${format(to, "HH:mm")}`;
|
|
392
|
+
return `${format(from, "MMM d, HH:mm")} – ${format(to, "MMM d, HH:mm")}`;
|
|
393
|
+
}
|
|
394
|
+
function filtersAreActive(filters) {
|
|
395
|
+
return Object.values(filters).some((values) => values.length > 0);
|
|
396
|
+
}
|
|
397
|
+
// src/components/features/logs/utils/url-state.ts
|
|
398
|
+
/**
|
|
399
|
+
* Query-string keys, before `prefix`. A preset range is written as
|
|
400
|
+
* `range=last-1h`; a hand-picked one as `from` and `to` ISO timestamps. Each
|
|
401
|
+
* selected facet value is its own `filter=<label>:<value>` entry.
|
|
402
|
+
*/
|
|
403
|
+
const LOGS_URL_KEYS = {
|
|
404
|
+
search: "q",
|
|
405
|
+
range: "range",
|
|
406
|
+
from: "from",
|
|
407
|
+
to: "to",
|
|
408
|
+
filter: "filter",
|
|
409
|
+
live: "live",
|
|
410
|
+
selected: "log"
|
|
411
|
+
};
|
|
412
|
+
/** Same rule as `buildLogQL`: anything else can't be a Loki label. */
|
|
413
|
+
const LABEL_NAME$1 = /^[a-z_]\w*$/i;
|
|
414
|
+
function keysFor(prefix = "") {
|
|
415
|
+
return {
|
|
416
|
+
search: `${prefix}${LOGS_URL_KEYS.search}`,
|
|
417
|
+
range: `${prefix}${LOGS_URL_KEYS.range}`,
|
|
418
|
+
from: `${prefix}${LOGS_URL_KEYS.from}`,
|
|
419
|
+
to: `${prefix}${LOGS_URL_KEYS.to}`,
|
|
420
|
+
filter: `${prefix}${LOGS_URL_KEYS.filter}`,
|
|
421
|
+
live: `${prefix}${LOGS_URL_KEYS.live}`,
|
|
422
|
+
selected: `${prefix}${LOGS_URL_KEYS.selected}`
|
|
423
|
+
};
|
|
424
|
+
}
|
|
425
|
+
function toParams(input) {
|
|
426
|
+
return typeof input === "string" ? new URLSearchParams(input) : input;
|
|
427
|
+
}
|
|
428
|
+
function isValidDate(value) {
|
|
429
|
+
return value !== null && value !== "" && !Number.isNaN(new Date(value).getTime());
|
|
430
|
+
}
|
|
431
|
+
function isKnownPreset(key) {
|
|
432
|
+
return LOG_TIME_PRESETS.some((preset) => preset.key === key);
|
|
433
|
+
}
|
|
434
|
+
function sameRange(a, b) {
|
|
435
|
+
if (a.preset || b.preset) return a.preset === b.preset;
|
|
436
|
+
return a.from === b.from && a.to === b.to;
|
|
437
|
+
}
|
|
438
|
+
function parseTimeRange(params, keys, fallback, now) {
|
|
439
|
+
const preset = params.get(keys.range);
|
|
440
|
+
if (preset && isKnownPreset(preset)) return resolveLogTimeRange({
|
|
441
|
+
from: "",
|
|
442
|
+
to: "",
|
|
443
|
+
preset
|
|
444
|
+
}, now);
|
|
445
|
+
const from = params.get(keys.from);
|
|
446
|
+
const to = params.get(keys.to);
|
|
447
|
+
if (isValidDate(from) && isValidDate(to) && new Date(from) < new Date(to)) return {
|
|
448
|
+
from: new Date(from).toISOString(),
|
|
449
|
+
to: new Date(to).toISOString()
|
|
450
|
+
};
|
|
451
|
+
return fallback.preset ? resolveLogTimeRange(fallback, now) : fallback;
|
|
452
|
+
}
|
|
453
|
+
function parseFilters(params, key) {
|
|
454
|
+
const filters = {};
|
|
455
|
+
for (const entry of params.getAll(key)) {
|
|
456
|
+
const split = entry.indexOf(":");
|
|
457
|
+
if (split <= 0) continue;
|
|
458
|
+
const name = entry.slice(0, split);
|
|
459
|
+
const value = entry.slice(split + 1);
|
|
460
|
+
if (!LABEL_NAME$1.test(name) || value === "") continue;
|
|
461
|
+
const values = filters[name] ?? (filters[name] = []);
|
|
462
|
+
if (!values.includes(value)) values.push(value);
|
|
463
|
+
}
|
|
464
|
+
return filters;
|
|
465
|
+
}
|
|
466
|
+
/**
|
|
467
|
+
* Read logs state from a query string. Missing or malformed values fall back
|
|
468
|
+
* to the defaults (`Logs.Root`'s own defaults), so a hand-edited or stale link
|
|
469
|
+
* still opens. A preset range is resolved against `now`.
|
|
470
|
+
*/
|
|
471
|
+
function parseLogsUrlState(input, options = {}) {
|
|
472
|
+
const params = toParams(input);
|
|
473
|
+
const keys = keysFor(options.prefix);
|
|
474
|
+
const now = options.now ?? /* @__PURE__ */ new Date();
|
|
475
|
+
const fallback = options.defaultTimeRange ?? lastThirtyMinutes(now);
|
|
476
|
+
const live = params.get(keys.live);
|
|
477
|
+
return {
|
|
478
|
+
timeRange: parseTimeRange(params, keys, fallback, now),
|
|
479
|
+
filters: parseFilters(params, keys.filter),
|
|
480
|
+
search: params.get(keys.search) ?? "",
|
|
481
|
+
live: live === "1" || live === "true",
|
|
482
|
+
selectedId: params.get(keys.selected) || null
|
|
483
|
+
};
|
|
484
|
+
}
|
|
485
|
+
/**
|
|
486
|
+
* Return a copy of `input` with the given parts of logs state written in.
|
|
487
|
+
* Only the parts present in `state` are touched, and params the app owns are
|
|
488
|
+
* kept. Defaults (no search, no filters, not live, the default range) are
|
|
489
|
+
* left out so a fresh explorer has a clean URL.
|
|
490
|
+
*/
|
|
491
|
+
function writeLogsUrlState(input, state, options = {}) {
|
|
492
|
+
const params = new URLSearchParams(toParams(input));
|
|
493
|
+
const keys = keysFor(options.prefix);
|
|
494
|
+
if (state.timeRange !== void 0) {
|
|
495
|
+
params.delete(keys.range);
|
|
496
|
+
params.delete(keys.from);
|
|
497
|
+
params.delete(keys.to);
|
|
498
|
+
const range = state.timeRange;
|
|
499
|
+
if (!sameRange(range, options.defaultTimeRange ?? {
|
|
500
|
+
from: "",
|
|
501
|
+
to: "",
|
|
502
|
+
preset: "last-30m"
|
|
503
|
+
})) {
|
|
504
|
+
if (range.preset && isKnownPreset(range.preset)) params.set(keys.range, range.preset);
|
|
505
|
+
else if (isValidDate(range.from) && isValidDate(range.to)) {
|
|
506
|
+
params.set(keys.from, range.from);
|
|
507
|
+
params.set(keys.to, range.to);
|
|
508
|
+
}
|
|
509
|
+
}
|
|
510
|
+
}
|
|
511
|
+
if (state.filters !== void 0) {
|
|
512
|
+
params.delete(keys.filter);
|
|
513
|
+
for (const [name, values] of Object.entries(state.filters)) {
|
|
514
|
+
if (!LABEL_NAME$1.test(name)) continue;
|
|
515
|
+
for (const value of values) if (value !== "") params.append(keys.filter, `${name}:${value}`);
|
|
516
|
+
}
|
|
517
|
+
}
|
|
518
|
+
if (state.search !== void 0) {
|
|
519
|
+
if (state.search === "") params.delete(keys.search);
|
|
520
|
+
else params.set(keys.search, state.search);
|
|
521
|
+
}
|
|
522
|
+
if (state.live !== void 0) {
|
|
523
|
+
if (state.live) params.set(keys.live, "1");
|
|
524
|
+
else params.delete(keys.live);
|
|
525
|
+
}
|
|
526
|
+
if (state.selectedId !== void 0) {
|
|
527
|
+
if (state.selectedId) params.set(keys.selected, state.selectedId);
|
|
528
|
+
else params.delete(keys.selected);
|
|
529
|
+
}
|
|
530
|
+
return params;
|
|
531
|
+
}
|
|
532
|
+
/**
|
|
533
|
+
* Just this explorer's params, as a query string in a fixed key order. It
|
|
534
|
+
* parses to the same state as the full query string, and only changes when
|
|
535
|
+
* one of these params does, so it works as a memo key: an unrelated app param
|
|
536
|
+
* changing won't re-resolve a preset range (which would hand the host a new
|
|
537
|
+
* `timeRange` and trigger a refetch).
|
|
538
|
+
*/
|
|
539
|
+
function logsUrlStateKey(input, options = {}) {
|
|
540
|
+
const params = toParams(input);
|
|
541
|
+
const own = new URLSearchParams();
|
|
542
|
+
for (const key of Object.values(keysFor(options.prefix))) for (const value of params.getAll(key)) own.append(key, value);
|
|
543
|
+
return own.toString();
|
|
544
|
+
}
|
|
545
|
+
// src/components/features/logs/hooks/use-logs-url-state.ts
|
|
546
|
+
/** pushState/replaceState don't fire `popstate`, so writes announce themselves. */
|
|
547
|
+
const LOCATION_CHANGE_EVENT = "datum-ui:logs-url-change";
|
|
548
|
+
function subscribeToLocation(onChange) {
|
|
549
|
+
window.addEventListener("popstate", onChange);
|
|
550
|
+
window.addEventListener(LOCATION_CHANGE_EVENT, onChange);
|
|
551
|
+
return () => {
|
|
552
|
+
window.removeEventListener("popstate", onChange);
|
|
553
|
+
window.removeEventListener(LOCATION_CHANGE_EVENT, onChange);
|
|
554
|
+
};
|
|
555
|
+
}
|
|
556
|
+
const getLocationSearch = () => window.location.search;
|
|
557
|
+
const getServerSearch = () => "";
|
|
558
|
+
const setWindowSearchParams = (update, options) => {
|
|
559
|
+
const next = update(new URLSearchParams(window.location.search)).toString();
|
|
560
|
+
const url = `${window.location.pathname}${next ? `?${next}` : ""}${window.location.hash}`;
|
|
561
|
+
if (options?.replace === false) window.history.pushState(window.history.state, "", url);
|
|
562
|
+
else window.history.replaceState(window.history.state, "", url);
|
|
563
|
+
window.dispatchEvent(new Event(LOCATION_CHANGE_EVENT));
|
|
564
|
+
};
|
|
565
|
+
/**
|
|
566
|
+
* Keep `Logs.Root`'s time range, filters, search, live toggle and open row in
|
|
567
|
+
* the address bar, so a refresh or a shared link reopens the same view.
|
|
568
|
+
*
|
|
569
|
+
* ```tsx
|
|
570
|
+
* const logsState = useLogsUrlState()
|
|
571
|
+
* const query = buildLogQL({ matchers: logsState.filters, lineContains: logsState.search })
|
|
572
|
+
* // fetch with query + resolveLogTimeRange(logsState.timeRange)
|
|
573
|
+
*
|
|
574
|
+
* <Logs.Root {...logsState} entries={entries} onRefresh={refetch}>
|
|
575
|
+
* <Logs.Explorer />
|
|
576
|
+
* </Logs.Root>
|
|
577
|
+
* ```
|
|
578
|
+
*
|
|
579
|
+
* With React Router, hand it the router's search params instead:
|
|
580
|
+
*
|
|
581
|
+
* ```tsx
|
|
582
|
+
* const [searchParams, setSearchParams] = useSearchParams()
|
|
583
|
+
* const logsState = useLogsUrlState({ searchParams, setSearchParams })
|
|
584
|
+
* ```
|
|
585
|
+
*/
|
|
586
|
+
function useLogsUrlState(options = {}) {
|
|
587
|
+
const { searchParams, setSearchParams, prefix = "", defaultTimeRange, history = "replace" } = options;
|
|
588
|
+
const locationSearch = useSyncExternalStore(subscribeToLocation, getLocationSearch, getServerSearch);
|
|
589
|
+
const write = setSearchParams ?? setWindowSearchParams;
|
|
590
|
+
const replace = history !== "push";
|
|
591
|
+
const hasDefault = defaultTimeRange !== void 0;
|
|
592
|
+
const defaultFrom = defaultTimeRange?.from;
|
|
593
|
+
const defaultTo = defaultTimeRange?.to;
|
|
594
|
+
const defaultPreset = defaultTimeRange?.preset;
|
|
595
|
+
const urlOptions = useMemo(() => ({
|
|
596
|
+
prefix,
|
|
597
|
+
defaultTimeRange: hasDefault ? {
|
|
598
|
+
from: defaultFrom ?? "",
|
|
599
|
+
to: defaultTo ?? "",
|
|
600
|
+
preset: defaultPreset
|
|
601
|
+
} : void 0
|
|
602
|
+
}), [
|
|
603
|
+
prefix,
|
|
604
|
+
hasDefault,
|
|
605
|
+
defaultFrom,
|
|
606
|
+
defaultTo,
|
|
607
|
+
defaultPreset
|
|
608
|
+
]);
|
|
609
|
+
const ownQuery = logsUrlStateKey(searchParams ?? locationSearch, { prefix });
|
|
610
|
+
const state = useMemo(() => parseLogsUrlState(ownQuery, urlOptions), [ownQuery, urlOptions]);
|
|
611
|
+
const update = useCallback((patch) => {
|
|
612
|
+
write((prev) => writeLogsUrlState(prev, patch, urlOptions), { replace });
|
|
613
|
+
}, [
|
|
614
|
+
write,
|
|
615
|
+
urlOptions,
|
|
616
|
+
replace
|
|
617
|
+
]);
|
|
618
|
+
const onTimeRangeChange = useCallback((timeRange) => update({ timeRange }), [update]);
|
|
619
|
+
const onFiltersChange = useCallback((filters) => update({ filters }), [update]);
|
|
620
|
+
const onSearchChange = useCallback((search) => update({ search }), [update]);
|
|
621
|
+
const onLiveChange = useCallback((live) => update({ live }), [update]);
|
|
622
|
+
const onSelectedIdChange = useCallback((selectedId) => update({ selectedId }), [update]);
|
|
623
|
+
return useMemo(() => ({
|
|
624
|
+
...state,
|
|
625
|
+
onTimeRangeChange,
|
|
626
|
+
onFiltersChange,
|
|
627
|
+
onSearchChange,
|
|
628
|
+
onLiveChange,
|
|
629
|
+
onSelectedIdChange
|
|
630
|
+
}), [
|
|
631
|
+
state,
|
|
632
|
+
onTimeRangeChange,
|
|
633
|
+
onFiltersChange,
|
|
634
|
+
onSearchChange,
|
|
635
|
+
onLiveChange,
|
|
636
|
+
onSelectedIdChange
|
|
637
|
+
]);
|
|
638
|
+
}
|
|
323
639
|
function clampLogsDetailWidth(width, maxWidth) {
|
|
324
640
|
return Math.min(Math.max(Math.round(width), 400), maxWidth > 400 ? maxWidth : 400);
|
|
325
641
|
}
|
|
@@ -1030,84 +1346,15 @@ function LogsDetail({ className }) {
|
|
|
1030
1346
|
}), /* @__PURE__ */ jsx(DetailBody, {})]
|
|
1031
1347
|
}) });
|
|
1032
1348
|
}
|
|
1033
|
-
// src/components/features/logs/utils/time-range.ts
|
|
1034
|
-
const MINUTE_MS$1 = 6e4;
|
|
1035
|
-
const HOUR_MS = 60 * MINUTE_MS$1;
|
|
1036
|
-
const DAY_MS$1 = 24 * HOUR_MS;
|
|
1037
|
-
function relativePreset(key, label, durationMs, shortcut) {
|
|
1038
|
-
return {
|
|
1039
|
-
key,
|
|
1040
|
-
label,
|
|
1041
|
-
shortcut,
|
|
1042
|
-
getRange: () => {
|
|
1043
|
-
const now = /* @__PURE__ */ new Date();
|
|
1044
|
-
return {
|
|
1045
|
-
from: new Date(now.getTime() - durationMs),
|
|
1046
|
-
to: now
|
|
1047
|
-
};
|
|
1048
|
-
}
|
|
1049
|
-
};
|
|
1050
|
-
}
|
|
1051
|
-
/**
|
|
1052
|
-
* Relative "Last N" windows offered by `Logs.Filters`. Keys are persisted on
|
|
1053
|
-
* `LogTimeRange.preset` so hosts can slide the window forward with
|
|
1054
|
-
* `resolveLogTimeRange` on refresh or while live tailing.
|
|
1055
|
-
*
|
|
1056
|
-
* Shortcuts follow the `picker` datetime presets (`1` / `2` / `H` / `W`) that
|
|
1057
|
-
* the logs picker is built on. Keys that mean something else in the pickers
|
|
1058
|
-
* (`3` is "Last 30 minutes" in `time-range-picker`, `D` is "Today") are not
|
|
1059
|
-
* reused, so muscle memory carries over between the two.
|
|
1060
|
-
*/
|
|
1061
|
-
const LOG_TIME_PRESETS = [
|
|
1062
|
-
relativePreset("last-15m", "Last 15 minutes", 15 * MINUTE_MS$1, "1"),
|
|
1063
|
-
relativePreset("last-30m", "Last 30 minutes", 30 * MINUTE_MS$1, "2"),
|
|
1064
|
-
relativePreset("last-1h", "Last hour", HOUR_MS, "H"),
|
|
1065
|
-
relativePreset("last-3h", "Last 3 hours", 3 * HOUR_MS),
|
|
1066
|
-
relativePreset("last-6h", "Last 6 hours", 6 * HOUR_MS, "6"),
|
|
1067
|
-
relativePreset("last-12h", "Last 12 hours", 12 * HOUR_MS),
|
|
1068
|
-
relativePreset("last-24h", "Last 24 hours", DAY_MS$1),
|
|
1069
|
-
relativePreset("last-7d", "Last 7 days", 7 * DAY_MS$1, "W")
|
|
1070
|
-
];
|
|
1071
|
-
function lastThirtyMinutes(now = /* @__PURE__ */ new Date()) {
|
|
1072
|
-
return {
|
|
1073
|
-
from: (/* @__PURE__ */ new Date(now.getTime() - 30 * MINUTE_MS$1)).toISOString(),
|
|
1074
|
-
to: now.toISOString(),
|
|
1075
|
-
preset: "last-30m"
|
|
1076
|
-
};
|
|
1077
|
-
}
|
|
1078
|
-
/**
|
|
1079
|
-
* Re-anchor a preset range to `now`. Absolute ranges (no `preset`, or an
|
|
1080
|
-
* unknown key) are returned unchanged.
|
|
1081
|
-
*/
|
|
1082
|
-
function resolveLogTimeRange(range, now = /* @__PURE__ */ new Date()) {
|
|
1083
|
-
if (!range.preset) return range;
|
|
1084
|
-
const preset = LOG_TIME_PRESETS.find((item) => item.key === range.preset);
|
|
1085
|
-
if (!preset) return range;
|
|
1086
|
-
const { from, to } = preset.getRange("UTC");
|
|
1087
|
-
const shift = now.getTime() - to.getTime();
|
|
1088
|
-
return {
|
|
1089
|
-
from: new Date(from.getTime() + shift).toISOString(),
|
|
1090
|
-
to: now.toISOString(),
|
|
1091
|
-
preset: range.preset
|
|
1092
|
-
};
|
|
1093
|
-
}
|
|
1094
|
-
/** Human label for the time-range trigger: preset name, or a compact absolute range. */
|
|
1095
|
-
function logTimeRangeLabel(range) {
|
|
1096
|
-
const preset = range.preset ? LOG_TIME_PRESETS.find((item) => item.key === range.preset) : void 0;
|
|
1097
|
-
if (preset) return preset.label;
|
|
1098
|
-
const from = new Date(range.from);
|
|
1099
|
-
const to = new Date(range.to);
|
|
1100
|
-
if (Number.isNaN(from.getTime()) || Number.isNaN(to.getTime())) return "Select range";
|
|
1101
|
-
if (isSameDay(from, to)) return `${format(from, "MMM d, HH:mm")} – ${format(to, "HH:mm")}`;
|
|
1102
|
-
return `${format(from, "MMM d, HH:mm")} – ${format(to, "MMM d, HH:mm")}`;
|
|
1103
|
-
}
|
|
1104
|
-
function filtersAreActive(filters) {
|
|
1105
|
-
return Object.values(filters).some((values) => values.length > 0);
|
|
1106
|
-
}
|
|
1107
1349
|
// src/components/features/logs/components/filters.tsx
|
|
1108
1350
|
function LogsFilterGroup({ facet, defaultOpen }) {
|
|
1109
1351
|
const { filters, toggleFilterValue } = useLogs();
|
|
1110
1352
|
const selected = filters[facet.name] ?? [];
|
|
1353
|
+
const known = new Set(facet.options.map((option) => option.value));
|
|
1354
|
+
const options = [...facet.options, ...selected.filter((value) => !known.has(value)).map((value) => ({
|
|
1355
|
+
value,
|
|
1356
|
+
count: void 0
|
|
1357
|
+
}))];
|
|
1111
1358
|
return /* @__PURE__ */ jsxs(Collapsible, {
|
|
1112
1359
|
defaultOpen,
|
|
1113
1360
|
className: "border-b border-border",
|
|
@@ -1119,7 +1366,7 @@ function LogsFilterGroup({ facet, defaultOpen }) {
|
|
|
1119
1366
|
})]
|
|
1120
1367
|
}), /* @__PURE__ */ jsx(CollapsibleContent, { children: /* @__PURE__ */ jsx("ul", {
|
|
1121
1368
|
className: "flex flex-col gap-1 px-3 pb-3",
|
|
1122
|
-
children:
|
|
1369
|
+
children: options.map((option) => /* @__PURE__ */ jsx("li", { children: /* @__PURE__ */ jsxs("label", {
|
|
1123
1370
|
className: "hover:bg-muted/40 flex cursor-pointer items-center gap-2 rounded-md px-1 py-1 text-sm",
|
|
1124
1371
|
children: [
|
|
1125
1372
|
/* @__PURE__ */ jsx(Checkbox, {
|
|
@@ -1596,7 +1843,7 @@ function LogsSearch({ placeholder = "Search logs...", className }) {
|
|
|
1596
1843
|
onChange: (event) => setValue(event.target.value),
|
|
1597
1844
|
placeholder,
|
|
1598
1845
|
"aria-label": placeholder,
|
|
1599
|
-
className: "pl-9",
|
|
1846
|
+
className: "h-9 pl-9",
|
|
1600
1847
|
"data-slot": "logs-search"
|
|
1601
1848
|
})]
|
|
1602
1849
|
});
|
|
@@ -1984,6 +2231,53 @@ function buildLogQL({ matchers, lineContains } = {}) {
|
|
|
1984
2231
|
if (!text) return selector;
|
|
1985
2232
|
return `${selector} |= "${escapeQuoted(text)}"`;
|
|
1986
2233
|
}
|
|
2234
|
+
// src/components/features/logs/utils/facet-counts.ts
|
|
2235
|
+
/** Same rule as `buildLogQL`: anything else can't be a Loki label. */
|
|
2236
|
+
const LABEL_NAME = /^[a-z_]\w*$/i;
|
|
2237
|
+
/** Whole seconds between `from` and `to`, at least 1. */
|
|
2238
|
+
function rangeSeconds({ from, to }) {
|
|
2239
|
+
const ms = new Date(to).getTime() - new Date(from).getTime();
|
|
2240
|
+
return Number.isFinite(ms) ? Math.max(1, Math.round(ms / 1e3)) : 1;
|
|
2241
|
+
}
|
|
2242
|
+
/**
|
|
2243
|
+
* LogQL that counts log lines per value of one label across a time range:
|
|
2244
|
+
*
|
|
2245
|
+
* ```
|
|
2246
|
+
* sum by (response_code) (count_over_time({route_name="my-alb"}[1800s]))
|
|
2247
|
+
* ```
|
|
2248
|
+
*
|
|
2249
|
+
* Run it as an instant query (`/loki/api/v1/query`) with `time` set to the
|
|
2250
|
+
* range's `to`, then pass the response to `facetFromLokiCounts`. Returns
|
|
2251
|
+
* `null` for a label name LogQL can't express. Works for indexed stream labels
|
|
2252
|
+
* and for structured metadata, which Loki can also group by.
|
|
2253
|
+
*/
|
|
2254
|
+
function buildLogFacetCountQuery({ label, matchers, timeRange }) {
|
|
2255
|
+
if (!LABEL_NAME.test(label)) return null;
|
|
2256
|
+
return `sum by (${label}) (count_over_time(${buildLogQL({ matchers })}[${rangeSeconds(timeRange)}s]))`;
|
|
2257
|
+
}
|
|
2258
|
+
/**
|
|
2259
|
+
* Turn the response to a `buildLogFacetCountQuery` query into a facet for
|
|
2260
|
+
* `Logs.Root`. Series without the label (lines that don't carry it) and zero
|
|
2261
|
+
* counts are skipped. Options are ordered the same way as `facetsFromEntries`.
|
|
2262
|
+
* Pass `label` to override the display name.
|
|
2263
|
+
*/
|
|
2264
|
+
function facetFromLokiCounts(name, response, options = {}) {
|
|
2265
|
+
const counts = /* @__PURE__ */ new Map();
|
|
2266
|
+
if (response?.status === "success" && response.data?.resultType === "vector") for (const sample of response.data.result) {
|
|
2267
|
+
const value = sample.metric[name];
|
|
2268
|
+
const count = Number(sample.value?.[1]);
|
|
2269
|
+
if (!value || !Number.isFinite(count) || count <= 0) continue;
|
|
2270
|
+
counts.set(value, (counts.get(value) ?? 0) + Math.round(count));
|
|
2271
|
+
}
|
|
2272
|
+
return {
|
|
2273
|
+
name,
|
|
2274
|
+
label: options.label ?? facetLabel(name),
|
|
2275
|
+
options: [...counts.entries()].sort(([a], [b]) => compareFacetValues(name, a, b)).map(([value, count]) => ({
|
|
2276
|
+
value,
|
|
2277
|
+
count
|
|
2278
|
+
}))
|
|
2279
|
+
};
|
|
2280
|
+
}
|
|
1987
2281
|
// src/components/features/logs/utils/flatten-loki.ts
|
|
1988
2282
|
function nsToDate(timestampNs) {
|
|
1989
2283
|
try {
|
|
@@ -2027,4 +2321,4 @@ function flattenLokiStreams(response) {
|
|
|
2027
2321
|
});
|
|
2028
2322
|
return entries;
|
|
2029
2323
|
}
|
|
2030
|
-
export { LOG_TIME_PRESETS, Logs, buildLogQL, facetsFromEntries, filterEntries, flattenLokiStreams, formatHttpLogLine, histogramFromEntries, httpStatusBadgeType, httpStatusTextClass, lastThirtyMinutes, logLineDisplay, logRequestHost, logTimeRangeLabel, logUserAgent, nsToDate, parseLogLine, parseUserAgent, resolveLogColumns, resolveLogTimeRange, searchableLogText, severityBadgeType, splitPathQuery, useLogs };
|
|
2324
|
+
export { LOGS_URL_KEYS, LOG_TIME_PRESETS, Logs, buildLogFacetCountQuery, buildLogQL, facetFromLokiCounts, facetsFromEntries, filterEntries, flattenLokiStreams, formatHttpLogLine, histogramFromEntries, httpStatusBadgeType, httpStatusTextClass, lastThirtyMinutes, logLineDisplay, logRequestHost, logTimeRangeLabel, logUserAgent, nsToDate, parseLogLine, parseLogsUrlState, parseUserAgent, resolveLogColumns, resolveLogTimeRange, searchableLogText, severityBadgeType, splitPathQuery, useLogs, useLogsUrlState, writeLogsUrlState };
|
package/dist/map/index.mjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export { k as Map, b as MapCircle, x as MapCircleMarker, h as MapControlContainer, o as MapDrawCircle, s as MapDrawControl, c as MapDrawDelete, l as MapDrawEdit, u as MapDrawMarker, d as MapDrawPolygon, f as MapDrawPolyline, p as MapDrawRectangle, m as MapDrawUndo, t as MapFeatureGroup, g as MapFullscreenControl, n as MapLayerGroup, r as MapLayers, i as MapLayersControl, _ as MapLocateControl, S as MapMarker, C as MapMarkerClusterGroup, w as MapPolygon, T as MapPolyline, E as MapPopup, D as MapRectangle, v as MapSearchControl, a as MapTileLayer, O as MapTooltip, y as MapZoomControl, j as PlaceAutocomplete, A as useLeaflet } from "../layers-
|
|
1
|
+
export { k as Map, b as MapCircle, x as MapCircleMarker, h as MapControlContainer, o as MapDrawCircle, s as MapDrawControl, c as MapDrawDelete, l as MapDrawEdit, u as MapDrawMarker, d as MapDrawPolygon, f as MapDrawPolyline, p as MapDrawRectangle, m as MapDrawUndo, t as MapFeatureGroup, g as MapFullscreenControl, n as MapLayerGroup, r as MapLayers, i as MapLayersControl, _ as MapLocateControl, S as MapMarker, C as MapMarkerClusterGroup, w as MapPolygon, T as MapPolyline, E as MapPopup, D as MapRectangle, v as MapSearchControl, a as MapTileLayer, O as MapTooltip, y as MapZoomControl, j as PlaceAutocomplete, A as useLeaflet } from "../layers-BC1Ny49w.mjs";
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { t as Button } from "./button-Cn4KagBO.mjs";
|
|
2
2
|
import { t as Tooltip } from "./tooltip-OIySjJWW.mjs";
|
|
3
3
|
import { t as cn } from "./utils-CTIuhCOs.mjs";
|
|
4
|
-
import { t as ResponsiveDropdown } from "./responsive-dropdown-
|
|
4
|
+
import { t as ResponsiveDropdown } from "./responsive-dropdown-B9cDUeHt.mjs";
|
|
5
5
|
import { t as ActionRow } from "./action-row-BEzE9x37.mjs";
|
|
6
6
|
import { Ellipsis } from "lucide-react";
|
|
7
7
|
import { useState } from "react";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export { t as MultiSelect } from "../multi-select-
|
|
1
|
+
export { t as MultiSelect } from "../multi-select-DwcsJdHt.mjs";
|