@flanksource/clicky-ui 0.2.14 → 0.2.15
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/chat.cjs +20 -0
- package/dist/chat.cjs.map +1 -0
- package/dist/chat.d.ts +2 -0
- package/dist/chat.d.ts.map +1 -0
- package/dist/chat.js +20 -0
- package/dist/chat.js.map +1 -0
- package/dist/components/Combobox.cjs +5 -3
- package/dist/components/Combobox.cjs.map +1 -1
- package/dist/components/Combobox.d.ts +2 -0
- package/dist/components/Combobox.d.ts.map +1 -1
- package/dist/components/Combobox.js +5 -3
- package/dist/components/Combobox.js.map +1 -1
- package/dist/components/DateTimePicker.cjs +3 -1
- package/dist/components/DateTimePicker.cjs.map +1 -1
- package/dist/components/DateTimePicker.d.ts +5 -1
- package/dist/components/DateTimePicker.d.ts.map +1 -1
- package/dist/components/DateTimePicker.js +3 -1
- package/dist/components/DateTimePicker.js.map +1 -1
- package/dist/components/FilterBar.cjs +8 -41
- package/dist/components/FilterBar.cjs.map +1 -1
- package/dist/components/FilterBar.d.ts +0 -2
- package/dist/components/FilterBar.d.ts.map +1 -1
- package/dist/components/FilterBar.js +3 -36
- package/dist/components/FilterBar.js.map +1 -1
- package/dist/components/FormatOptionsDropdown.cjs +2 -18
- package/dist/components/FormatOptionsDropdown.cjs.map +1 -1
- package/dist/components/FormatOptionsDropdown.d.ts +1 -17
- package/dist/components/FormatOptionsDropdown.d.ts.map +1 -1
- package/dist/components/FormatOptionsDropdown.js +1 -17
- package/dist/components/FormatOptionsDropdown.js.map +1 -1
- package/dist/components/JsonSchemaForm.cjs +128 -12
- package/dist/components/JsonSchemaForm.cjs.map +1 -1
- package/dist/components/JsonSchemaForm.d.ts +1 -1
- package/dist/components/JsonSchemaForm.d.ts.map +1 -1
- package/dist/components/JsonSchemaForm.js +131 -15
- package/dist/components/JsonSchemaForm.js.map +1 -1
- package/dist/components/SecretKeySelector.cjs +0 -1
- package/dist/components/SecretKeySelector.cjs.map +1 -1
- package/dist/components/SecretKeySelector.d.ts +0 -2
- package/dist/components/SecretKeySelector.d.ts.map +1 -1
- package/dist/components/SecretKeySelector.js +1 -2
- package/dist/components/SecretKeySelector.js.map +1 -1
- package/dist/components/TreePickerField.cjs +137 -0
- package/dist/components/TreePickerField.cjs.map +1 -0
- package/dist/components/TreePickerField.d.ts +30 -0
- package/dist/components/TreePickerField.d.ts.map +1 -0
- package/dist/components/TreePickerField.js +137 -0
- package/dist/components/TreePickerField.js.map +1 -0
- package/dist/components/WorkloadPicker.cjs +6 -81
- package/dist/components/WorkloadPicker.cjs.map +1 -1
- package/dist/components/WorkloadPicker.d.ts +1 -20
- package/dist/components/WorkloadPicker.d.ts.map +1 -1
- package/dist/components/WorkloadPicker.js +3 -78
- package/dist/components/WorkloadPicker.js.map +1 -1
- package/dist/components/button-variants.cjs +30 -0
- package/dist/components/button-variants.cjs.map +1 -0
- package/dist/components/button-variants.d.ts +5 -0
- package/dist/components/button-variants.d.ts.map +1 -0
- package/dist/components/button-variants.js +30 -0
- package/dist/components/button-variants.js.map +1 -0
- package/dist/components/button.cjs +11 -82
- package/dist/components/button.cjs.map +1 -1
- package/dist/components/button.d.ts +1 -5
- package/dist/components/button.d.ts.map +1 -1
- package/dist/components/button.js +5 -76
- package/dist/components/button.js.map +1 -1
- package/dist/components/filter-bar-utils.cjs +37 -0
- package/dist/components/filter-bar-utils.cjs.map +1 -0
- package/dist/components/filter-bar-utils.d.ts +4 -0
- package/dist/components/filter-bar-utils.d.ts.map +1 -0
- package/dist/components/filter-bar-utils.js +37 -0
- package/dist/components/filter-bar-utils.js.map +1 -0
- package/dist/components/format-options.cjs +20 -0
- package/dist/components/format-options.cjs.map +1 -0
- package/dist/components/format-options.d.ts +18 -0
- package/dist/components/format-options.d.ts.map +1 -0
- package/dist/components/format-options.js +20 -0
- package/dist/components/format-options.js.map +1 -0
- package/dist/components/json-schema-form-array.cjs +13 -17
- package/dist/components/json-schema-form-array.cjs.map +1 -1
- package/dist/components/json-schema-form-array.d.ts +1 -2
- package/dist/components/json-schema-form-array.d.ts.map +1 -1
- package/dist/components/json-schema-form-array.js +3 -7
- package/dist/components/json-schema-form-array.js.map +1 -1
- package/dist/components/json-schema-form-fields.cjs +90 -232
- package/dist/components/json-schema-form-fields.cjs.map +1 -1
- package/dist/components/json-schema-form-fields.d.ts +51 -6
- package/dist/components/json-schema-form-fields.d.ts.map +1 -1
- package/dist/components/json-schema-form-fields.js +82 -224
- package/dist/components/json-schema-form-fields.js.map +1 -1
- package/dist/components/json-schema-form-object.cjs +149 -0
- package/dist/components/json-schema-form-object.cjs.map +1 -0
- package/dist/components/json-schema-form-object.d.ts +10 -0
- package/dist/components/json-schema-form-object.d.ts.map +1 -0
- package/dist/components/json-schema-form-object.js +149 -0
- package/dist/components/json-schema-form-object.js.map +1 -0
- package/dist/components/json-schema-form-preferences.cjs +41 -0
- package/dist/components/json-schema-form-preferences.cjs.map +1 -0
- package/dist/components/json-schema-form-preferences.d.ts +10 -0
- package/dist/components/json-schema-form-preferences.d.ts.map +1 -0
- package/dist/components/json-schema-form-preferences.js +41 -0
- package/dist/components/json-schema-form-preferences.js.map +1 -0
- package/dist/components/json-schema-form-render.cjs +43 -72
- package/dist/components/json-schema-form-render.cjs.map +1 -1
- package/dist/components/json-schema-form-render.d.ts +5 -33
- package/dist/components/json-schema-form-render.d.ts.map +1 -1
- package/dist/components/json-schema-form-render.js +41 -70
- package/dist/components/json-schema-form-render.js.map +1 -1
- package/dist/components/json-schema-form-resolve.cjs +9 -1
- package/dist/components/json-schema-form-resolve.cjs.map +1 -1
- package/dist/components/json-schema-form-resolve.d.ts.map +1 -1
- package/dist/components/json-schema-form-resolve.js +9 -1
- package/dist/components/json-schema-form-resolve.js.map +1 -1
- package/dist/components/json-schema-form-types.d.ts +58 -1
- package/dist/components/json-schema-form-types.d.ts.map +1 -1
- package/dist/components/json-schema-form-utils.cjs +96 -0
- package/dist/components/json-schema-form-utils.cjs.map +1 -0
- package/dist/components/json-schema-form-utils.d.ts +17 -0
- package/dist/components/json-schema-form-utils.d.ts.map +1 -0
- package/dist/components/json-schema-form-utils.js +96 -0
- package/dist/components/json-schema-form-utils.js.map +1 -0
- package/dist/components/loading.cjs +109 -0
- package/dist/components/loading.cjs.map +1 -0
- package/dist/components/loading.d.ts +27 -0
- package/dist/components/loading.d.ts.map +1 -0
- package/dist/components/loading.js +109 -0
- package/dist/components/loading.js.map +1 -0
- package/dist/components/workload-picker-utils.cjs +88 -0
- package/dist/components/workload-picker-utils.cjs.map +1 -0
- package/dist/components/workload-picker-utils.d.ts +34 -0
- package/dist/components/workload-picker-utils.d.ts.map +1 -0
- package/dist/components/workload-picker-utils.js +88 -0
- package/dist/components/workload-picker-utils.js.map +1 -0
- package/dist/components.cjs +18 -6
- package/dist/components.cjs.map +1 -1
- package/dist/components.d.ts +10 -3
- package/dist/components.d.ts.map +1 -1
- package/dist/components.js +16 -4
- package/dist/components.js.map +1 -1
- package/dist/data/Badge.cjs +11 -91
- package/dist/data/Badge.cjs.map +1 -1
- package/dist/data/Badge.d.ts +1 -5
- package/dist/data/Badge.d.ts.map +1 -1
- package/dist/data/Badge.js +11 -91
- package/dist/data/Badge.js.map +1 -1
- package/dist/data/Clicky.cjs +4 -3
- package/dist/data/Clicky.cjs.map +1 -1
- package/dist/data/Clicky.d.ts.map +1 -1
- package/dist/data/Clicky.js +4 -3
- package/dist/data/Clicky.js.map +1 -1
- package/dist/data/DataTable.cjs +161 -156
- package/dist/data/DataTable.cjs.map +1 -1
- package/dist/data/DataTable.d.ts +25 -4
- package/dist/data/DataTable.d.ts.map +1 -1
- package/dist/data/DataTable.js +140 -135
- package/dist/data/DataTable.js.map +1 -1
- package/dist/data/FilterPill.cjs +3 -0
- package/dist/data/FilterPill.cjs.map +1 -1
- package/dist/data/FilterPill.d.ts.map +1 -1
- package/dist/data/FilterPill.js +3 -0
- package/dist/data/FilterPill.js.map +1 -1
- package/dist/data/Icon.cjs +7 -7
- package/dist/data/Icon.cjs.map +1 -1
- package/dist/data/Icon.js +7 -7
- package/dist/data/Icon.js.map +1 -1
- package/dist/data/LogDetails.cjs +5 -14
- package/dist/data/LogDetails.cjs.map +1 -1
- package/dist/data/LogDetails.d.ts +8 -4
- package/dist/data/LogDetails.d.ts.map +1 -1
- package/dist/data/LogDetails.js +4 -13
- package/dist/data/LogDetails.js.map +1 -1
- package/dist/data/LogsTable.cjs +6 -165
- package/dist/data/LogsTable.cjs.map +1 -1
- package/dist/data/LogsTable.d.ts +2 -15
- package/dist/data/LogsTable.d.ts.map +1 -1
- package/dist/data/LogsTable.js +6 -165
- package/dist/data/LogsTable.js.map +1 -1
- package/dist/data/TimeseriesPanel.axes.cjs.map +1 -1
- package/dist/data/TimeseriesPanel.axes.js.map +1 -1
- package/dist/data/TreeNode.cjs +13 -7
- package/dist/data/TreeNode.cjs.map +1 -1
- package/dist/data/TreeNode.d.ts.map +1 -1
- package/dist/data/TreeNode.js +13 -7
- package/dist/data/TreeNode.js.map +1 -1
- package/dist/data/badge-variants.cjs +85 -0
- package/dist/data/badge-variants.cjs.map +1 -0
- package/dist/data/badge-variants.d.ts +6 -0
- package/dist/data/badge-variants.d.ts.map +1 -0
- package/dist/data/badge-variants.js +85 -0
- package/dist/data/badge-variants.js.map +1 -0
- package/dist/data/cache-browser/CacheBrowser.cjs +59 -0
- package/dist/data/cache-browser/CacheBrowser.cjs.map +1 -0
- package/dist/data/cache-browser/CacheBrowser.d.ts +26 -0
- package/dist/data/cache-browser/CacheBrowser.d.ts.map +1 -0
- package/dist/data/cache-browser/CacheBrowser.js +59 -0
- package/dist/data/cache-browser/CacheBrowser.js.map +1 -0
- package/dist/data/cache-browser/CacheDetailPanel.cjs +193 -0
- package/dist/data/cache-browser/CacheDetailPanel.cjs.map +1 -0
- package/dist/data/cache-browser/CacheDetailPanel.d.ts +20 -0
- package/dist/data/cache-browser/CacheDetailPanel.d.ts.map +1 -0
- package/dist/data/cache-browser/CacheDetailPanel.js +193 -0
- package/dist/data/cache-browser/CacheDetailPanel.js.map +1 -0
- package/dist/data/cache-browser/CacheStatsOverview.cjs +126 -0
- package/dist/data/cache-browser/CacheStatsOverview.cjs.map +1 -0
- package/dist/data/cache-browser/CacheStatsOverview.d.ts +17 -0
- package/dist/data/cache-browser/CacheStatsOverview.d.ts.map +1 -0
- package/dist/data/cache-browser/CacheStatsOverview.js +126 -0
- package/dist/data/cache-browser/CacheStatsOverview.js.map +1 -0
- package/dist/data/cache-browser/CacheTree.cjs +189 -0
- package/dist/data/cache-browser/CacheTree.cjs.map +1 -0
- package/dist/data/cache-browser/CacheTree.d.ts +27 -0
- package/dist/data/cache-browser/CacheTree.d.ts.map +1 -0
- package/dist/data/cache-browser/CacheTree.js +189 -0
- package/dist/data/cache-browser/CacheTree.js.map +1 -0
- package/dist/data/cache-browser/CacheValue.cjs +86 -0
- package/dist/data/cache-browser/CacheValue.cjs.map +1 -0
- package/dist/data/cache-browser/CacheValue.d.ts +11 -0
- package/dist/data/cache-browser/CacheValue.d.ts.map +1 -0
- package/dist/data/cache-browser/CacheValue.js +86 -0
- package/dist/data/cache-browser/CacheValue.js.map +1 -0
- package/dist/data/cache-browser/adapter.cjs +52 -0
- package/dist/data/cache-browser/adapter.cjs.map +1 -0
- package/dist/data/cache-browser/adapter.d.ts +48 -0
- package/dist/data/cache-browser/adapter.d.ts.map +1 -0
- package/dist/data/cache-browser/adapter.js +52 -0
- package/dist/data/cache-browser/adapter.js.map +1 -0
- package/dist/data/cache-browser/api.cjs +42 -0
- package/dist/data/cache-browser/api.cjs.map +1 -0
- package/dist/data/cache-browser/api.d.ts +33 -0
- package/dist/data/cache-browser/api.d.ts.map +1 -0
- package/dist/data/cache-browser/api.js +42 -0
- package/dist/data/cache-browser/api.js.map +1 -0
- package/dist/data/cache-browser/index.d.ts +9 -0
- package/dist/data/cache-browser/index.d.ts.map +1 -0
- package/dist/data/cache-browser/types.cjs +7 -0
- package/dist/data/cache-browser/types.cjs.map +1 -0
- package/dist/data/cache-browser/types.d.ts +78 -0
- package/dist/data/cache-browser/types.d.ts.map +1 -0
- package/dist/data/cache-browser/types.js +7 -0
- package/dist/data/cache-browser/types.js.map +1 -0
- package/dist/data/cells/TagList.cjs +4 -101
- package/dist/data/cells/TagList.cjs.map +1 -1
- package/dist/data/cells/TagList.d.ts +1 -49
- package/dist/data/cells/TagList.d.ts.map +1 -1
- package/dist/data/cells/TagList.js +3 -100
- package/dist/data/cells/TagList.js.map +1 -1
- package/dist/data/cells/Timestamp.cjs +3 -192
- package/dist/data/cells/Timestamp.cjs.map +1 -1
- package/dist/data/cells/Timestamp.d.ts +1 -50
- package/dist/data/cells/Timestamp.d.ts.map +1 -1
- package/dist/data/cells/Timestamp.js +2 -191
- package/dist/data/cells/Timestamp.js.map +1 -1
- package/dist/data/cells/tag-utils.cjs +103 -0
- package/dist/data/cells/tag-utils.cjs.map +1 -0
- package/dist/data/cells/tag-utils.d.ts +51 -0
- package/dist/data/cells/tag-utils.d.ts.map +1 -0
- package/dist/data/cells/tag-utils.js +103 -0
- package/dist/data/cells/tag-utils.js.map +1 -0
- package/dist/data/cells/timestamp-format.cjs +193 -0
- package/dist/data/cells/timestamp-format.cjs.map +1 -0
- package/dist/data/cells/timestamp-format.d.ts +51 -0
- package/dist/data/cells/timestamp-format.d.ts.map +1 -0
- package/dist/data/cells/timestamp-format.js +193 -0
- package/dist/data/cells/timestamp-format.js.map +1 -0
- package/dist/data/chat/Chat.cjs +48 -0
- package/dist/data/chat/Chat.cjs.map +1 -0
- package/dist/data/chat/Chat.d.ts +26 -0
- package/dist/data/chat/Chat.d.ts.map +1 -0
- package/dist/data/chat/Chat.fixtures.d.ts +6 -0
- package/dist/data/chat/Chat.fixtures.d.ts.map +1 -0
- package/dist/data/chat/Chat.js +48 -0
- package/dist/data/chat/Chat.js.map +1 -0
- package/dist/data/chat/Conversation.cjs +34 -0
- package/dist/data/chat/Conversation.cjs.map +1 -0
- package/dist/data/chat/Conversation.d.ts +11 -0
- package/dist/data/chat/Conversation.d.ts.map +1 -0
- package/dist/data/chat/Conversation.js +34 -0
- package/dist/data/chat/Conversation.js.map +1 -0
- package/dist/data/chat/Message.cjs +44 -0
- package/dist/data/chat/Message.cjs.map +1 -0
- package/dist/data/chat/Message.d.ts +10 -0
- package/dist/data/chat/Message.d.ts.map +1 -0
- package/dist/data/chat/Message.js +44 -0
- package/dist/data/chat/Message.js.map +1 -0
- package/dist/data/chat/PromptInput.cjs +61 -0
- package/dist/data/chat/PromptInput.cjs.map +1 -0
- package/dist/data/chat/PromptInput.d.ts +16 -0
- package/dist/data/chat/PromptInput.d.ts.map +1 -0
- package/dist/data/chat/PromptInput.js +61 -0
- package/dist/data/chat/PromptInput.js.map +1 -0
- package/dist/data/chat/ToolCall.cjs +92 -0
- package/dist/data/chat/ToolCall.cjs.map +1 -0
- package/dist/data/chat/ToolCall.d.ts +14 -0
- package/dist/data/chat/ToolCall.d.ts.map +1 -0
- package/dist/data/chat/ToolCall.js +92 -0
- package/dist/data/chat/ToolCall.js.map +1 -0
- package/dist/data/chat/clickyOperationsToTools.cjs +73 -0
- package/dist/data/chat/clickyOperationsToTools.cjs.map +1 -0
- package/dist/data/chat/clickyOperationsToTools.d.ts +10 -0
- package/dist/data/chat/clickyOperationsToTools.d.ts.map +1 -0
- package/dist/data/chat/clickyOperationsToTools.js +73 -0
- package/dist/data/chat/clickyOperationsToTools.js.map +1 -0
- package/dist/data/chat/index.d.ts +8 -0
- package/dist/data/chat/index.d.ts.map +1 -0
- package/dist/data/chat/types.cjs +18 -0
- package/dist/data/chat/types.cjs.map +1 -0
- package/dist/data/chat/types.d.ts +41 -0
- package/dist/data/chat/types.d.ts.map +1 -0
- package/dist/data/chat/types.js +18 -0
- package/dist/data/chat/types.js.map +1 -0
- package/dist/data/data-table-utils.cjs +55 -0
- package/dist/data/data-table-utils.cjs.map +1 -0
- package/dist/data/data-table-utils.d.ts +24 -0
- package/dist/data/data-table-utils.d.ts.map +1 -0
- package/dist/data/data-table-utils.js +55 -0
- package/dist/data/data-table-utils.js.map +1 -0
- package/dist/data/diagnostics/DiagnosticsDetailPanel.cjs +2 -1
- package/dist/data/diagnostics/DiagnosticsDetailPanel.cjs.map +1 -1
- package/dist/data/diagnostics/DiagnosticsDetailPanel.d.ts.map +1 -1
- package/dist/data/diagnostics/DiagnosticsDetailPanel.js +3 -2
- package/dist/data/diagnostics/DiagnosticsDetailPanel.js.map +1 -1
- package/dist/data/diagnostics/GoroutineCard.cjs +3 -22
- package/dist/data/diagnostics/GoroutineCard.cjs.map +1 -1
- package/dist/data/diagnostics/GoroutineCard.d.ts +0 -2
- package/dist/data/diagnostics/GoroutineCard.d.ts.map +1 -1
- package/dist/data/diagnostics/GoroutineCard.js +2 -21
- package/dist/data/diagnostics/GoroutineCard.js.map +1 -1
- package/dist/data/diagnostics/ThreadCard.cjs +3 -38
- package/dist/data/diagnostics/ThreadCard.cjs.map +1 -1
- package/dist/data/diagnostics/ThreadCard.d.ts +0 -2
- package/dist/data/diagnostics/ThreadCard.d.ts.map +1 -1
- package/dist/data/diagnostics/ThreadCard.js +2 -37
- package/dist/data/diagnostics/ThreadCard.js.map +1 -1
- package/dist/data/diagnostics/state-styles.cjs +59 -0
- package/dist/data/diagnostics/state-styles.cjs.map +1 -0
- package/dist/data/diagnostics/state-styles.d.ts +5 -0
- package/dist/data/diagnostics/state-styles.d.ts.map +1 -0
- package/dist/data/diagnostics/state-styles.js +59 -0
- package/dist/data/diagnostics/state-styles.js.map +1 -0
- package/dist/data/logs-normalize.cjs +166 -0
- package/dist/data/logs-normalize.cjs.map +1 -0
- package/dist/data/logs-normalize.d.ts +16 -0
- package/dist/data/logs-normalize.d.ts.map +1 -0
- package/dist/data/logs-normalize.js +166 -0
- package/dist/data/logs-normalize.js.map +1 -0
- package/dist/data/task-status.cjs +19 -19
- package/dist/data/task-status.cjs.map +1 -1
- package/dist/data/task-status.js +19 -19
- package/dist/data/task-status.js.map +1 -1
- package/dist/data/version-info.cjs +3 -3
- package/dist/data/version-info.js +3 -3
- package/dist/data.cjs +43 -18
- package/dist/data.cjs.map +1 -1
- package/dist/data.d.ts +11 -5
- package/dist/data.d.ts.map +1 -1
- package/dist/data.js +30 -5
- package/dist/data.js.map +1 -1
- package/dist/hooks/density-provider.cjs +38 -0
- package/dist/hooks/density-provider.cjs.map +1 -0
- package/dist/hooks/density-provider.d.ts +20 -0
- package/dist/hooks/density-provider.d.ts.map +1 -0
- package/dist/hooks/density-provider.js +38 -0
- package/dist/hooks/density-provider.js.map +1 -0
- package/dist/hooks/theme-provider.cjs +43 -0
- package/dist/hooks/theme-provider.cjs.map +1 -0
- package/dist/hooks/theme-provider.d.ts +9 -0
- package/dist/hooks/theme-provider.d.ts.map +1 -0
- package/dist/hooks/theme-provider.js +43 -0
- package/dist/hooks/theme-provider.js.map +1 -0
- package/dist/hooks/use-density.cjs +8 -37
- package/dist/hooks/use-density.cjs.map +1 -1
- package/dist/hooks/use-density.d.ts +5 -20
- package/dist/hooks/use-density.d.ts.map +1 -1
- package/dist/hooks/use-density.js +9 -38
- package/dist/hooks/use-density.js.map +1 -1
- package/dist/hooks/use-theme.cjs +10 -43
- package/dist/hooks/use-theme.cjs.map +1 -1
- package/dist/hooks/use-theme.d.ts +6 -9
- package/dist/hooks/use-theme.d.ts.map +1 -1
- package/dist/hooks/use-theme.js +11 -44
- package/dist/hooks/use-theme.js.map +1 -1
- package/dist/hooks.cjs +5 -2
- package/dist/hooks.cjs.map +1 -1
- package/dist/hooks.d.ts +4 -2
- package/dist/hooks.d.ts.map +1 -1
- package/dist/hooks.js +5 -2
- package/dist/hooks.js.map +1 -1
- package/dist/icons/changeIconAliases.cjs +13 -13
- package/dist/icons/changeIconAliases.cjs.map +1 -1
- package/dist/icons/changeIconAliases.d.ts.map +1 -1
- package/dist/icons/changeIconAliases.js +13 -13
- package/dist/icons/changeIconAliases.js.map +1 -1
- package/dist/index.cjs +71 -30
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +53 -12
- package/dist/index.js.map +1 -1
- package/dist/overlay/DropdownMenu.cjs +2 -0
- package/dist/overlay/DropdownMenu.cjs.map +1 -1
- package/dist/overlay/DropdownMenu.d.ts +3 -1
- package/dist/overlay/DropdownMenu.d.ts.map +1 -1
- package/dist/overlay/DropdownMenu.js +2 -0
- package/dist/overlay/DropdownMenu.js.map +1 -1
- package/dist/overlay/Modal.cjs +11 -4
- package/dist/overlay/Modal.cjs.map +1 -1
- package/dist/overlay/Modal.d.ts +1 -1
- package/dist/overlay/Modal.d.ts.map +1 -1
- package/dist/overlay/Modal.js +11 -4
- package/dist/overlay/Modal.js.map +1 -1
- package/dist/overlay/modalStack.cjs +35 -0
- package/dist/overlay/modalStack.cjs.map +1 -0
- package/dist/overlay/modalStack.d.ts +13 -0
- package/dist/overlay/modalStack.d.ts.map +1 -0
- package/dist/overlay/modalStack.js +35 -0
- package/dist/overlay/modalStack.js.map +1 -0
- package/dist/rpc/AcceptPicker.cjs +2 -18
- package/dist/rpc/AcceptPicker.cjs.map +1 -1
- package/dist/rpc/AcceptPicker.d.ts +1 -41
- package/dist/rpc/AcceptPicker.d.ts.map +1 -1
- package/dist/rpc/AcceptPicker.js +2 -18
- package/dist/rpc/AcceptPicker.js.map +1 -1
- package/dist/rpc/CommandOutput.cjs +1 -1
- package/dist/rpc/CommandOutput.cjs.map +1 -1
- package/dist/rpc/CommandOutput.js +1 -1
- package/dist/rpc/CommandOutput.js.map +1 -1
- package/dist/rpc/EndpointList.cjs +1 -1
- package/dist/rpc/EndpointList.cjs.map +1 -1
- package/dist/rpc/EndpointList.js +1 -1
- package/dist/rpc/EndpointList.js.map +1 -1
- package/dist/rpc/OperationCatalog.cjs +23 -41
- package/dist/rpc/OperationCatalog.cjs.map +1 -1
- package/dist/rpc/OperationCatalog.d.ts.map +1 -1
- package/dist/rpc/OperationCatalog.js +24 -42
- package/dist/rpc/OperationCatalog.js.map +1 -1
- package/dist/rpc/OperationCommandPage.cjs.map +1 -1
- package/dist/rpc/OperationCommandPage.d.ts.map +1 -1
- package/dist/rpc/OperationCommandPage.js.map +1 -1
- package/dist/rpc/accept-options.cjs +20 -0
- package/dist/rpc/accept-options.cjs.map +1 -0
- package/dist/rpc/accept-options.d.ts +42 -0
- package/dist/rpc/accept-options.d.ts.map +1 -0
- package/dist/rpc/accept-options.js +20 -0
- package/dist/rpc/accept-options.js.map +1 -0
- package/dist/rpc/classify.cjs +15 -4
- package/dist/rpc/classify.cjs.map +1 -1
- package/dist/rpc/classify.d.ts.map +1 -1
- package/dist/rpc/classify.js +15 -4
- package/dist/rpc/classify.js.map +1 -1
- package/dist/rpc/clickyMetadata.cjs +13 -3
- package/dist/rpc/clickyMetadata.cjs.map +1 -1
- package/dist/rpc/clickyMetadata.d.ts +2 -0
- package/dist/rpc/clickyMetadata.d.ts.map +1 -1
- package/dist/rpc/clickyMetadata.js +14 -4
- package/dist/rpc/clickyMetadata.js.map +1 -1
- package/dist/rpc.cjs +3 -2
- package/dist/rpc.cjs.map +1 -1
- package/dist/rpc.d.ts +2 -1
- package/dist/rpc.d.ts.map +1 -1
- package/dist/rpc.js +2 -1
- package/dist/rpc.js.map +1 -1
- package/dist/styles.css +1 -1
- package/package.json +16 -1
package/dist/data/FilterPill.cjs
CHANGED
|
@@ -69,6 +69,9 @@ function TristateSwitch({
|
|
|
69
69
|
{
|
|
70
70
|
"aria-hidden": true,
|
|
71
71
|
className: utils.cn(
|
|
72
|
+
// The knob stays white in BOTH themes (standard switch look): on the
|
|
73
|
+
// dark-mode muted/red/green tracks white is the high-contrast choice,
|
|
74
|
+
// while bg-background would vanish against the track.
|
|
72
75
|
"pointer-events-none absolute left-0.5 top-0.5 z-20 flex size-4 items-center justify-center rounded-full bg-white shadow-sm transition-transform duration-150",
|
|
73
76
|
SLOT_TRANSLATE[slot]
|
|
74
77
|
),
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"FilterPill.cjs","sources":["../../src/data/FilterPill.tsx"],"sourcesContent":["import type { ReactNode } from \"react\";\nimport { cn } from \"../lib/utils\";\nimport { Icon, type StaticIconComponent } from \"./Icon\";\nimport { UiAdd, UiCheck, UiClose, UiRemove } from \"../icons\";\n\nexport type FilterMode = \"active\" | \"neutral\" | \"include\" | \"exclude\";\n\nexport type FilterPillProps = {\n /** Visual and semantic state for the pill. */\n mode?: FilterMode;\n /** Primary visible label. */\n label: ReactNode;\n /** Optional count badge rendered before the label. */\n count?: number;\n /** Iconify name or imported icon component. */\n icon?: string | StaticIconComponent;\n /** Classes for the count badge background. */\n badge?: string;\n /**\n * Tri-state handler. When provided the pill renders as a toggle with a left\n * minus (exclude) and right plus (include) region. Clicking a side toggles\n * that state against \"neutral\"; clicking the label cycles neutral → include\n * → exclude → neutral.\n */\n onModeChange?: (next: FilterMode) => void;\n /** Legacy single-click handler, used when onModeChange is not provided. */\n onClick?: () => void;\n /** Browser tooltip and accessible label for tri-state controls. */\n title?: string;\n /** Places the tri-state toggle before or after the label. */\n togglePosition?: \"left\" | \"right\";\n /** Classes applied to the pill root. */\n className?: string;\n};\n\nfunction bodyClasses(mode: FilterMode): string {\n switch (mode) {\n case \"active\":\n return \"bg-primary/10 border-primary/40 text-primary font-medium\";\n case \"include\":\n return \"bg-green-500/10 border-green-500/50 text-green-700 dark:text-green-400 font-medium\";\n case \"exclude\":\n return \"bg-red-500/10 border-red-500/50 text-red-700 dark:text-red-400 font-medium\";\n case \"neutral\":\n default:\n return \"border-border text-muted-foreground hover:bg-accent\";\n }\n}\n\ntype SlotMode = \"exclude\" | \"neutral\" | \"include\";\n\nconst SLOT_TRANSLATE: Record<SlotMode, string> = {\n exclude: \"translate-x-0\",\n neutral: \"translate-x-4\",\n include: \"translate-x-8\",\n};\n\nfunction TristateSwitch({\n mode,\n onChange,\n ariaLabel,\n}: {\n mode: FilterMode;\n onChange: (next: FilterMode) => void;\n ariaLabel?: string;\n}) {\n const slot: SlotMode =\n mode === \"exclude\" ? \"exclude\" : mode === \"include\" ? \"include\" : \"neutral\";\n const bg =\n slot === \"exclude\" ? \"bg-red-500/80\" : slot === \"include\" ? \"bg-green-500/80\" : \"bg-muted\";\n\n // The three regions are aria-hidden click targets layered over the toggle\n // track: clicking the left edge toggles exclude, the right edge toggles\n // include, and the middle rotates. They are NOT focusable buttons — the\n // whole switch is a single <button> so it exposes one accessible name and\n // does not pollute the accessible name of any FilterBar wrapper that hosts\n // it (e.g. the multi-filter option row, which is itself a role=\"button\").\n const region = (next: FilterMode, regionMode: SlotMode) => (\n <span\n aria-hidden\n data-tristate-region={regionMode}\n onClick={(event) => {\n event.preventDefault();\n event.stopPropagation();\n onChange(next);\n }}\n className=\"relative z-10 h-full flex-1 cursor-pointer\"\n />\n );\n\n return (\n <button\n type=\"button\"\n aria-label={ariaLabel}\n title={ariaLabel}\n onClick={(event) => {\n // Keyboard activation (Enter/Space) lands here without a region —\n // cycle, matching the middle-region rotation.\n event.preventDefault();\n event.stopPropagation();\n onChange(nextTriStateMode(mode));\n }}\n className={cn(\n \"relative inline-flex h-5 w-[52px] shrink-0 overflow-hidden rounded-full transition-colors duration-200\",\n bg,\n )}\n >\n {region(mode === \"exclude\" ? \"neutral\" : \"exclude\", \"exclude\")}\n {region(nextTriStateMode(mode), \"neutral\")}\n {region(mode === \"include\" ? \"neutral\" : \"include\", \"include\")}\n <span\n aria-hidden\n className={cn(\n \"pointer-events-none absolute left-0.5 top-0.5 z-20 flex size-4 items-center justify-center rounded-full bg-white shadow-sm transition-transform duration-150\",\n SLOT_TRANSLATE[slot],\n )}\n >\n {slot !== \"neutral\" && (\n <Icon\n icon={slot === \"exclude\" ? UiClose : UiCheck}\n className={cn(\n \"text-[10px]\",\n slot === \"exclude\" && \"text-red-600\",\n slot === \"include\" && \"text-green-600\",\n )}\n />\n )}\n </span>\n </button>\n );\n}\n\nexport function FilterPill({\n mode = \"neutral\",\n label,\n count,\n icon,\n badge,\n onModeChange,\n onClick,\n title,\n togglePosition = \"left\",\n className,\n}: FilterPillProps) {\n const triState = !!onModeChange;\n const content = (\n <>\n {count !== undefined && (\n <span\n className={cn(\n \"inline-flex items-center justify-center min-w-[16px] h-[16px] px-1 rounded-full text-[10px] font-bold text-white\",\n badge ?? \"bg-muted-foreground\",\n )}\n >\n {count}\n </span>\n )}\n {icon && (\n <Icon {...(typeof icon === \"string\" ? { name: icon } : { icon })} className=\"text-sm\" />\n )}\n <span className=\"truncate\">{label}</span>\n </>\n );\n\n if (triState) {\n const control = (\n <TristateSwitch\n mode={mode}\n onChange={onModeChange!}\n {...(title ? { ariaLabel: title } : {})}\n />\n );\n const labelContent = (\n <span className=\"inline-flex min-w-0 items-center gap-1.5 text-xs text-foreground\">\n {content}\n </span>\n );\n\n return (\n <span className={cn(\"inline-flex items-center gap-1.5 select-none\", className)} title={title}>\n {togglePosition === \"right\" ? (\n <>\n {labelContent}\n {control}\n </>\n ) : (\n <>\n {control}\n {labelContent}\n </>\n )}\n </span>\n );\n }\n\n return (\n <button\n type=\"button\"\n onClick={onClick}\n title={title}\n className={cn(\n \"inline-flex items-center gap-1.5 text-xs px-2 py-0.5 rounded-full border transition-colors\",\n bodyClasses(mode),\n className,\n )}\n >\n <LegacyMarker mode={mode} />\n {content}\n </button>\n );\n}\n\nfunction LegacyMarker({ mode }: { mode: FilterMode }) {\n if (mode === \"include\") return <Icon icon={UiAdd} className=\"text-xs\" />;\n if (mode === \"exclude\") return <Icon icon={UiRemove} className=\"text-xs\" />;\n if (mode === \"active\") return <span className=\"w-2 h-2 rounded-full bg-current\" />;\n return <span className=\"w-2 h-2 rounded-full bg-current opacity-30\" />;\n}\n\nfunction nextTriStateMode(mode: FilterMode): FilterMode {\n if (mode === \"include\") return \"exclude\";\n if (mode === \"exclude\") return \"neutral\";\n return \"include\";\n}\n\nexport type FilterPillGroupProps = {\n /** Filter pills or separators to lay out. */\n children: ReactNode;\n /** Classes applied to the wrapping row. */\n className?: string;\n};\n\nexport function FilterPillGroup({ children, className }: FilterPillGroupProps) {\n return <div className={cn(\"flex items-center gap-1.5 flex-wrap\", className)}>{children}</div>;\n}\n\nexport function FilterSeparator() {\n return (\n <span aria-hidden className=\"text-border mx-0.5\">\n |\n </span>\n );\n}\n"],"names":["jsx","jsxs","cn","Icon","UiClose","UiCheck","Fragment","UiAdd","UiRemove"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"FilterPill.cjs","sources":["../../src/data/FilterPill.tsx"],"sourcesContent":["import type { ReactNode } from \"react\";\nimport { cn } from \"../lib/utils\";\nimport { Icon, type StaticIconComponent } from \"./Icon\";\nimport { UiAdd, UiCheck, UiClose, UiRemove } from \"../icons\";\n\nexport type FilterMode = \"active\" | \"neutral\" | \"include\" | \"exclude\";\n\nexport type FilterPillProps = {\n /** Visual and semantic state for the pill. */\n mode?: FilterMode;\n /** Primary visible label. */\n label: ReactNode;\n /** Optional count badge rendered before the label. */\n count?: number;\n /** Iconify name or imported icon component. */\n icon?: string | StaticIconComponent;\n /** Classes for the count badge background. */\n badge?: string;\n /**\n * Tri-state handler. When provided the pill renders as a toggle with a left\n * minus (exclude) and right plus (include) region. Clicking a side toggles\n * that state against \"neutral\"; clicking the label cycles neutral → include\n * → exclude → neutral.\n */\n onModeChange?: (next: FilterMode) => void;\n /** Legacy single-click handler, used when onModeChange is not provided. */\n onClick?: () => void;\n /** Browser tooltip and accessible label for tri-state controls. */\n title?: string;\n /** Places the tri-state toggle before or after the label. */\n togglePosition?: \"left\" | \"right\";\n /** Classes applied to the pill root. */\n className?: string;\n};\n\nfunction bodyClasses(mode: FilterMode): string {\n switch (mode) {\n case \"active\":\n return \"bg-primary/10 border-primary/40 text-primary font-medium\";\n case \"include\":\n return \"bg-green-500/10 border-green-500/50 text-green-700 dark:text-green-400 font-medium\";\n case \"exclude\":\n return \"bg-red-500/10 border-red-500/50 text-red-700 dark:text-red-400 font-medium\";\n case \"neutral\":\n default:\n return \"border-border text-muted-foreground hover:bg-accent\";\n }\n}\n\ntype SlotMode = \"exclude\" | \"neutral\" | \"include\";\n\nconst SLOT_TRANSLATE: Record<SlotMode, string> = {\n exclude: \"translate-x-0\",\n neutral: \"translate-x-4\",\n include: \"translate-x-8\",\n};\n\nfunction TristateSwitch({\n mode,\n onChange,\n ariaLabel,\n}: {\n mode: FilterMode;\n onChange: (next: FilterMode) => void;\n ariaLabel?: string;\n}) {\n const slot: SlotMode =\n mode === \"exclude\" ? \"exclude\" : mode === \"include\" ? \"include\" : \"neutral\";\n const bg =\n slot === \"exclude\" ? \"bg-red-500/80\" : slot === \"include\" ? \"bg-green-500/80\" : \"bg-muted\";\n\n // The three regions are aria-hidden click targets layered over the toggle\n // track: clicking the left edge toggles exclude, the right edge toggles\n // include, and the middle rotates. They are NOT focusable buttons — the\n // whole switch is a single <button> so it exposes one accessible name and\n // does not pollute the accessible name of any FilterBar wrapper that hosts\n // it (e.g. the multi-filter option row, which is itself a role=\"button\").\n const region = (next: FilterMode, regionMode: SlotMode) => (\n <span\n aria-hidden\n data-tristate-region={regionMode}\n onClick={(event) => {\n event.preventDefault();\n event.stopPropagation();\n onChange(next);\n }}\n className=\"relative z-10 h-full flex-1 cursor-pointer\"\n />\n );\n\n return (\n <button\n type=\"button\"\n aria-label={ariaLabel}\n title={ariaLabel}\n onClick={(event) => {\n // Keyboard activation (Enter/Space) lands here without a region —\n // cycle, matching the middle-region rotation.\n event.preventDefault();\n event.stopPropagation();\n onChange(nextTriStateMode(mode));\n }}\n className={cn(\n \"relative inline-flex h-5 w-[52px] shrink-0 overflow-hidden rounded-full transition-colors duration-200\",\n bg,\n )}\n >\n {region(mode === \"exclude\" ? \"neutral\" : \"exclude\", \"exclude\")}\n {region(nextTriStateMode(mode), \"neutral\")}\n {region(mode === \"include\" ? \"neutral\" : \"include\", \"include\")}\n <span\n aria-hidden\n className={cn(\n // The knob stays white in BOTH themes (standard switch look): on the\n // dark-mode muted/red/green tracks white is the high-contrast choice,\n // while bg-background would vanish against the track.\n \"pointer-events-none absolute left-0.5 top-0.5 z-20 flex size-4 items-center justify-center rounded-full bg-white shadow-sm transition-transform duration-150\",\n SLOT_TRANSLATE[slot],\n )}\n >\n {slot !== \"neutral\" && (\n <Icon\n icon={slot === \"exclude\" ? UiClose : UiCheck}\n className={cn(\n \"text-[10px]\",\n slot === \"exclude\" && \"text-red-600\",\n slot === \"include\" && \"text-green-600\",\n )}\n />\n )}\n </span>\n </button>\n );\n}\n\nexport function FilterPill({\n mode = \"neutral\",\n label,\n count,\n icon,\n badge,\n onModeChange,\n onClick,\n title,\n togglePosition = \"left\",\n className,\n}: FilterPillProps) {\n const triState = !!onModeChange;\n const content = (\n <>\n {count !== undefined && (\n <span\n className={cn(\n \"inline-flex items-center justify-center min-w-[16px] h-[16px] px-1 rounded-full text-[10px] font-bold text-white\",\n badge ?? \"bg-muted-foreground\",\n )}\n >\n {count}\n </span>\n )}\n {icon && (\n <Icon {...(typeof icon === \"string\" ? { name: icon } : { icon })} className=\"text-sm\" />\n )}\n <span className=\"truncate\">{label}</span>\n </>\n );\n\n if (triState) {\n const control = (\n <TristateSwitch\n mode={mode}\n onChange={onModeChange!}\n {...(title ? { ariaLabel: title } : {})}\n />\n );\n const labelContent = (\n <span className=\"inline-flex min-w-0 items-center gap-1.5 text-xs text-foreground\">\n {content}\n </span>\n );\n\n return (\n <span className={cn(\"inline-flex items-center gap-1.5 select-none\", className)} title={title}>\n {togglePosition === \"right\" ? (\n <>\n {labelContent}\n {control}\n </>\n ) : (\n <>\n {control}\n {labelContent}\n </>\n )}\n </span>\n );\n }\n\n return (\n <button\n type=\"button\"\n onClick={onClick}\n title={title}\n className={cn(\n \"inline-flex items-center gap-1.5 text-xs px-2 py-0.5 rounded-full border transition-colors\",\n bodyClasses(mode),\n className,\n )}\n >\n <LegacyMarker mode={mode} />\n {content}\n </button>\n );\n}\n\nfunction LegacyMarker({ mode }: { mode: FilterMode }) {\n if (mode === \"include\") return <Icon icon={UiAdd} className=\"text-xs\" />;\n if (mode === \"exclude\") return <Icon icon={UiRemove} className=\"text-xs\" />;\n if (mode === \"active\") return <span className=\"w-2 h-2 rounded-full bg-current\" />;\n return <span className=\"w-2 h-2 rounded-full bg-current opacity-30\" />;\n}\n\nfunction nextTriStateMode(mode: FilterMode): FilterMode {\n if (mode === \"include\") return \"exclude\";\n if (mode === \"exclude\") return \"neutral\";\n return \"include\";\n}\n\nexport type FilterPillGroupProps = {\n /** Filter pills or separators to lay out. */\n children: ReactNode;\n /** Classes applied to the wrapping row. */\n className?: string;\n};\n\nexport function FilterPillGroup({ children, className }: FilterPillGroupProps) {\n return <div className={cn(\"flex items-center gap-1.5 flex-wrap\", className)}>{children}</div>;\n}\n\nexport function FilterSeparator() {\n return (\n <span aria-hidden className=\"text-border mx-0.5\">\n |\n </span>\n );\n}\n"],"names":["jsx","jsxs","cn","Icon","UiClose","UiCheck","Fragment","UiAdd","UiRemove"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"FilterPill.d.ts","sourceRoot":"","sources":["../../src/data/FilterPill.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAEvC,OAAO,EAAQ,KAAK,mBAAmB,EAAE,MAAM,QAAQ,CAAC;AAGxD,MAAM,MAAM,UAAU,GAAG,QAAQ,GAAG,SAAS,GAAG,SAAS,GAAG,SAAS,CAAC;AAEtE,MAAM,MAAM,eAAe,GAAG;IAC5B,8CAA8C;IAC9C,IAAI,CAAC,EAAE,UAAU,CAAC;IAClB,6BAA6B;IAC7B,KAAK,EAAE,SAAS,CAAC;IACjB,sDAAsD;IACtD,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,+CAA+C;IAC/C,IAAI,CAAC,EAAE,MAAM,GAAG,mBAAmB,CAAC;IACpC,8CAA8C;IAC9C,KAAK,CAAC,EAAE,MAAM,CAAC;IACf;;;;;OAKG;IACH,YAAY,CAAC,EAAE,CAAC,IAAI,EAAE,UAAU,KAAK,IAAI,CAAC;IAC1C,2EAA2E;IAC3E,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;IACrB,mEAAmE;IACnE,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,6DAA6D;IAC7D,cAAc,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC;IAClC,wCAAwC;IACxC,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB,CAAC;
|
|
1
|
+
{"version":3,"file":"FilterPill.d.ts","sourceRoot":"","sources":["../../src/data/FilterPill.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAEvC,OAAO,EAAQ,KAAK,mBAAmB,EAAE,MAAM,QAAQ,CAAC;AAGxD,MAAM,MAAM,UAAU,GAAG,QAAQ,GAAG,SAAS,GAAG,SAAS,GAAG,SAAS,CAAC;AAEtE,MAAM,MAAM,eAAe,GAAG;IAC5B,8CAA8C;IAC9C,IAAI,CAAC,EAAE,UAAU,CAAC;IAClB,6BAA6B;IAC7B,KAAK,EAAE,SAAS,CAAC;IACjB,sDAAsD;IACtD,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,+CAA+C;IAC/C,IAAI,CAAC,EAAE,MAAM,GAAG,mBAAmB,CAAC;IACpC,8CAA8C;IAC9C,KAAK,CAAC,EAAE,MAAM,CAAC;IACf;;;;;OAKG;IACH,YAAY,CAAC,EAAE,CAAC,IAAI,EAAE,UAAU,KAAK,IAAI,CAAC;IAC1C,2EAA2E;IAC3E,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;IACrB,mEAAmE;IACnE,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,6DAA6D;IAC7D,cAAc,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC;IAClC,wCAAwC;IACxC,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB,CAAC;AAsGF,wBAAgB,UAAU,CAAC,EACzB,IAAgB,EAChB,KAAK,EACL,KAAK,EACL,IAAI,EACJ,KAAK,EACL,YAAY,EACZ,OAAO,EACP,KAAK,EACL,cAAuB,EACvB,SAAS,GACV,EAAE,eAAe,2CAmEjB;AAeD,MAAM,MAAM,oBAAoB,GAAG;IACjC,6CAA6C;IAC7C,QAAQ,EAAE,SAAS,CAAC;IACpB,2CAA2C;IAC3C,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB,CAAC;AAEF,wBAAgB,eAAe,CAAC,EAAE,QAAQ,EAAE,SAAS,EAAE,EAAE,oBAAoB,2CAE5E;AAED,wBAAgB,eAAe,4CAM9B"}
|
package/dist/data/FilterPill.js
CHANGED
|
@@ -67,6 +67,9 @@ function TristateSwitch({
|
|
|
67
67
|
{
|
|
68
68
|
"aria-hidden": true,
|
|
69
69
|
className: cn(
|
|
70
|
+
// The knob stays white in BOTH themes (standard switch look): on the
|
|
71
|
+
// dark-mode muted/red/green tracks white is the high-contrast choice,
|
|
72
|
+
// while bg-background would vanish against the track.
|
|
70
73
|
"pointer-events-none absolute left-0.5 top-0.5 z-20 flex size-4 items-center justify-center rounded-full bg-white shadow-sm transition-transform duration-150",
|
|
71
74
|
SLOT_TRANSLATE[slot]
|
|
72
75
|
),
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"FilterPill.js","sources":["../../src/data/FilterPill.tsx"],"sourcesContent":["import type { ReactNode } from \"react\";\nimport { cn } from \"../lib/utils\";\nimport { Icon, type StaticIconComponent } from \"./Icon\";\nimport { UiAdd, UiCheck, UiClose, UiRemove } from \"../icons\";\n\nexport type FilterMode = \"active\" | \"neutral\" | \"include\" | \"exclude\";\n\nexport type FilterPillProps = {\n /** Visual and semantic state for the pill. */\n mode?: FilterMode;\n /** Primary visible label. */\n label: ReactNode;\n /** Optional count badge rendered before the label. */\n count?: number;\n /** Iconify name or imported icon component. */\n icon?: string | StaticIconComponent;\n /** Classes for the count badge background. */\n badge?: string;\n /**\n * Tri-state handler. When provided the pill renders as a toggle with a left\n * minus (exclude) and right plus (include) region. Clicking a side toggles\n * that state against \"neutral\"; clicking the label cycles neutral → include\n * → exclude → neutral.\n */\n onModeChange?: (next: FilterMode) => void;\n /** Legacy single-click handler, used when onModeChange is not provided. */\n onClick?: () => void;\n /** Browser tooltip and accessible label for tri-state controls. */\n title?: string;\n /** Places the tri-state toggle before or after the label. */\n togglePosition?: \"left\" | \"right\";\n /** Classes applied to the pill root. */\n className?: string;\n};\n\nfunction bodyClasses(mode: FilterMode): string {\n switch (mode) {\n case \"active\":\n return \"bg-primary/10 border-primary/40 text-primary font-medium\";\n case \"include\":\n return \"bg-green-500/10 border-green-500/50 text-green-700 dark:text-green-400 font-medium\";\n case \"exclude\":\n return \"bg-red-500/10 border-red-500/50 text-red-700 dark:text-red-400 font-medium\";\n case \"neutral\":\n default:\n return \"border-border text-muted-foreground hover:bg-accent\";\n }\n}\n\ntype SlotMode = \"exclude\" | \"neutral\" | \"include\";\n\nconst SLOT_TRANSLATE: Record<SlotMode, string> = {\n exclude: \"translate-x-0\",\n neutral: \"translate-x-4\",\n include: \"translate-x-8\",\n};\n\nfunction TristateSwitch({\n mode,\n onChange,\n ariaLabel,\n}: {\n mode: FilterMode;\n onChange: (next: FilterMode) => void;\n ariaLabel?: string;\n}) {\n const slot: SlotMode =\n mode === \"exclude\" ? \"exclude\" : mode === \"include\" ? \"include\" : \"neutral\";\n const bg =\n slot === \"exclude\" ? \"bg-red-500/80\" : slot === \"include\" ? \"bg-green-500/80\" : \"bg-muted\";\n\n // The three regions are aria-hidden click targets layered over the toggle\n // track: clicking the left edge toggles exclude, the right edge toggles\n // include, and the middle rotates. They are NOT focusable buttons — the\n // whole switch is a single <button> so it exposes one accessible name and\n // does not pollute the accessible name of any FilterBar wrapper that hosts\n // it (e.g. the multi-filter option row, which is itself a role=\"button\").\n const region = (next: FilterMode, regionMode: SlotMode) => (\n <span\n aria-hidden\n data-tristate-region={regionMode}\n onClick={(event) => {\n event.preventDefault();\n event.stopPropagation();\n onChange(next);\n }}\n className=\"relative z-10 h-full flex-1 cursor-pointer\"\n />\n );\n\n return (\n <button\n type=\"button\"\n aria-label={ariaLabel}\n title={ariaLabel}\n onClick={(event) => {\n // Keyboard activation (Enter/Space) lands here without a region —\n // cycle, matching the middle-region rotation.\n event.preventDefault();\n event.stopPropagation();\n onChange(nextTriStateMode(mode));\n }}\n className={cn(\n \"relative inline-flex h-5 w-[52px] shrink-0 overflow-hidden rounded-full transition-colors duration-200\",\n bg,\n )}\n >\n {region(mode === \"exclude\" ? \"neutral\" : \"exclude\", \"exclude\")}\n {region(nextTriStateMode(mode), \"neutral\")}\n {region(mode === \"include\" ? \"neutral\" : \"include\", \"include\")}\n <span\n aria-hidden\n className={cn(\n \"pointer-events-none absolute left-0.5 top-0.5 z-20 flex size-4 items-center justify-center rounded-full bg-white shadow-sm transition-transform duration-150\",\n SLOT_TRANSLATE[slot],\n )}\n >\n {slot !== \"neutral\" && (\n <Icon\n icon={slot === \"exclude\" ? UiClose : UiCheck}\n className={cn(\n \"text-[10px]\",\n slot === \"exclude\" && \"text-red-600\",\n slot === \"include\" && \"text-green-600\",\n )}\n />\n )}\n </span>\n </button>\n );\n}\n\nexport function FilterPill({\n mode = \"neutral\",\n label,\n count,\n icon,\n badge,\n onModeChange,\n onClick,\n title,\n togglePosition = \"left\",\n className,\n}: FilterPillProps) {\n const triState = !!onModeChange;\n const content = (\n <>\n {count !== undefined && (\n <span\n className={cn(\n \"inline-flex items-center justify-center min-w-[16px] h-[16px] px-1 rounded-full text-[10px] font-bold text-white\",\n badge ?? \"bg-muted-foreground\",\n )}\n >\n {count}\n </span>\n )}\n {icon && (\n <Icon {...(typeof icon === \"string\" ? { name: icon } : { icon })} className=\"text-sm\" />\n )}\n <span className=\"truncate\">{label}</span>\n </>\n );\n\n if (triState) {\n const control = (\n <TristateSwitch\n mode={mode}\n onChange={onModeChange!}\n {...(title ? { ariaLabel: title } : {})}\n />\n );\n const labelContent = (\n <span className=\"inline-flex min-w-0 items-center gap-1.5 text-xs text-foreground\">\n {content}\n </span>\n );\n\n return (\n <span className={cn(\"inline-flex items-center gap-1.5 select-none\", className)} title={title}>\n {togglePosition === \"right\" ? (\n <>\n {labelContent}\n {control}\n </>\n ) : (\n <>\n {control}\n {labelContent}\n </>\n )}\n </span>\n );\n }\n\n return (\n <button\n type=\"button\"\n onClick={onClick}\n title={title}\n className={cn(\n \"inline-flex items-center gap-1.5 text-xs px-2 py-0.5 rounded-full border transition-colors\",\n bodyClasses(mode),\n className,\n )}\n >\n <LegacyMarker mode={mode} />\n {content}\n </button>\n );\n}\n\nfunction LegacyMarker({ mode }: { mode: FilterMode }) {\n if (mode === \"include\") return <Icon icon={UiAdd} className=\"text-xs\" />;\n if (mode === \"exclude\") return <Icon icon={UiRemove} className=\"text-xs\" />;\n if (mode === \"active\") return <span className=\"w-2 h-2 rounded-full bg-current\" />;\n return <span className=\"w-2 h-2 rounded-full bg-current opacity-30\" />;\n}\n\nfunction nextTriStateMode(mode: FilterMode): FilterMode {\n if (mode === \"include\") return \"exclude\";\n if (mode === \"exclude\") return \"neutral\";\n return \"include\";\n}\n\nexport type FilterPillGroupProps = {\n /** Filter pills or separators to lay out. */\n children: ReactNode;\n /** Classes applied to the wrapping row. */\n className?: string;\n};\n\nexport function FilterPillGroup({ children, className }: FilterPillGroupProps) {\n return <div className={cn(\"flex items-center gap-1.5 flex-wrap\", className)}>{children}</div>;\n}\n\nexport function FilterSeparator() {\n return (\n <span aria-hidden className=\"text-border mx-0.5\">\n |\n </span>\n );\n}\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"FilterPill.js","sources":["../../src/data/FilterPill.tsx"],"sourcesContent":["import type { ReactNode } from \"react\";\nimport { cn } from \"../lib/utils\";\nimport { Icon, type StaticIconComponent } from \"./Icon\";\nimport { UiAdd, UiCheck, UiClose, UiRemove } from \"../icons\";\n\nexport type FilterMode = \"active\" | \"neutral\" | \"include\" | \"exclude\";\n\nexport type FilterPillProps = {\n /** Visual and semantic state for the pill. */\n mode?: FilterMode;\n /** Primary visible label. */\n label: ReactNode;\n /** Optional count badge rendered before the label. */\n count?: number;\n /** Iconify name or imported icon component. */\n icon?: string | StaticIconComponent;\n /** Classes for the count badge background. */\n badge?: string;\n /**\n * Tri-state handler. When provided the pill renders as a toggle with a left\n * minus (exclude) and right plus (include) region. Clicking a side toggles\n * that state against \"neutral\"; clicking the label cycles neutral → include\n * → exclude → neutral.\n */\n onModeChange?: (next: FilterMode) => void;\n /** Legacy single-click handler, used when onModeChange is not provided. */\n onClick?: () => void;\n /** Browser tooltip and accessible label for tri-state controls. */\n title?: string;\n /** Places the tri-state toggle before or after the label. */\n togglePosition?: \"left\" | \"right\";\n /** Classes applied to the pill root. */\n className?: string;\n};\n\nfunction bodyClasses(mode: FilterMode): string {\n switch (mode) {\n case \"active\":\n return \"bg-primary/10 border-primary/40 text-primary font-medium\";\n case \"include\":\n return \"bg-green-500/10 border-green-500/50 text-green-700 dark:text-green-400 font-medium\";\n case \"exclude\":\n return \"bg-red-500/10 border-red-500/50 text-red-700 dark:text-red-400 font-medium\";\n case \"neutral\":\n default:\n return \"border-border text-muted-foreground hover:bg-accent\";\n }\n}\n\ntype SlotMode = \"exclude\" | \"neutral\" | \"include\";\n\nconst SLOT_TRANSLATE: Record<SlotMode, string> = {\n exclude: \"translate-x-0\",\n neutral: \"translate-x-4\",\n include: \"translate-x-8\",\n};\n\nfunction TristateSwitch({\n mode,\n onChange,\n ariaLabel,\n}: {\n mode: FilterMode;\n onChange: (next: FilterMode) => void;\n ariaLabel?: string;\n}) {\n const slot: SlotMode =\n mode === \"exclude\" ? \"exclude\" : mode === \"include\" ? \"include\" : \"neutral\";\n const bg =\n slot === \"exclude\" ? \"bg-red-500/80\" : slot === \"include\" ? \"bg-green-500/80\" : \"bg-muted\";\n\n // The three regions are aria-hidden click targets layered over the toggle\n // track: clicking the left edge toggles exclude, the right edge toggles\n // include, and the middle rotates. They are NOT focusable buttons — the\n // whole switch is a single <button> so it exposes one accessible name and\n // does not pollute the accessible name of any FilterBar wrapper that hosts\n // it (e.g. the multi-filter option row, which is itself a role=\"button\").\n const region = (next: FilterMode, regionMode: SlotMode) => (\n <span\n aria-hidden\n data-tristate-region={regionMode}\n onClick={(event) => {\n event.preventDefault();\n event.stopPropagation();\n onChange(next);\n }}\n className=\"relative z-10 h-full flex-1 cursor-pointer\"\n />\n );\n\n return (\n <button\n type=\"button\"\n aria-label={ariaLabel}\n title={ariaLabel}\n onClick={(event) => {\n // Keyboard activation (Enter/Space) lands here without a region —\n // cycle, matching the middle-region rotation.\n event.preventDefault();\n event.stopPropagation();\n onChange(nextTriStateMode(mode));\n }}\n className={cn(\n \"relative inline-flex h-5 w-[52px] shrink-0 overflow-hidden rounded-full transition-colors duration-200\",\n bg,\n )}\n >\n {region(mode === \"exclude\" ? \"neutral\" : \"exclude\", \"exclude\")}\n {region(nextTriStateMode(mode), \"neutral\")}\n {region(mode === \"include\" ? \"neutral\" : \"include\", \"include\")}\n <span\n aria-hidden\n className={cn(\n // The knob stays white in BOTH themes (standard switch look): on the\n // dark-mode muted/red/green tracks white is the high-contrast choice,\n // while bg-background would vanish against the track.\n \"pointer-events-none absolute left-0.5 top-0.5 z-20 flex size-4 items-center justify-center rounded-full bg-white shadow-sm transition-transform duration-150\",\n SLOT_TRANSLATE[slot],\n )}\n >\n {slot !== \"neutral\" && (\n <Icon\n icon={slot === \"exclude\" ? UiClose : UiCheck}\n className={cn(\n \"text-[10px]\",\n slot === \"exclude\" && \"text-red-600\",\n slot === \"include\" && \"text-green-600\",\n )}\n />\n )}\n </span>\n </button>\n );\n}\n\nexport function FilterPill({\n mode = \"neutral\",\n label,\n count,\n icon,\n badge,\n onModeChange,\n onClick,\n title,\n togglePosition = \"left\",\n className,\n}: FilterPillProps) {\n const triState = !!onModeChange;\n const content = (\n <>\n {count !== undefined && (\n <span\n className={cn(\n \"inline-flex items-center justify-center min-w-[16px] h-[16px] px-1 rounded-full text-[10px] font-bold text-white\",\n badge ?? \"bg-muted-foreground\",\n )}\n >\n {count}\n </span>\n )}\n {icon && (\n <Icon {...(typeof icon === \"string\" ? { name: icon } : { icon })} className=\"text-sm\" />\n )}\n <span className=\"truncate\">{label}</span>\n </>\n );\n\n if (triState) {\n const control = (\n <TristateSwitch\n mode={mode}\n onChange={onModeChange!}\n {...(title ? { ariaLabel: title } : {})}\n />\n );\n const labelContent = (\n <span className=\"inline-flex min-w-0 items-center gap-1.5 text-xs text-foreground\">\n {content}\n </span>\n );\n\n return (\n <span className={cn(\"inline-flex items-center gap-1.5 select-none\", className)} title={title}>\n {togglePosition === \"right\" ? (\n <>\n {labelContent}\n {control}\n </>\n ) : (\n <>\n {control}\n {labelContent}\n </>\n )}\n </span>\n );\n }\n\n return (\n <button\n type=\"button\"\n onClick={onClick}\n title={title}\n className={cn(\n \"inline-flex items-center gap-1.5 text-xs px-2 py-0.5 rounded-full border transition-colors\",\n bodyClasses(mode),\n className,\n )}\n >\n <LegacyMarker mode={mode} />\n {content}\n </button>\n );\n}\n\nfunction LegacyMarker({ mode }: { mode: FilterMode }) {\n if (mode === \"include\") return <Icon icon={UiAdd} className=\"text-xs\" />;\n if (mode === \"exclude\") return <Icon icon={UiRemove} className=\"text-xs\" />;\n if (mode === \"active\") return <span className=\"w-2 h-2 rounded-full bg-current\" />;\n return <span className=\"w-2 h-2 rounded-full bg-current opacity-30\" />;\n}\n\nfunction nextTriStateMode(mode: FilterMode): FilterMode {\n if (mode === \"include\") return \"exclude\";\n if (mode === \"exclude\") return \"neutral\";\n return \"include\";\n}\n\nexport type FilterPillGroupProps = {\n /** Filter pills or separators to lay out. */\n children: ReactNode;\n /** Classes applied to the wrapping row. */\n className?: string;\n};\n\nexport function FilterPillGroup({ children, className }: FilterPillGroupProps) {\n return <div className={cn(\"flex items-center gap-1.5 flex-wrap\", className)}>{children}</div>;\n}\n\nexport function FilterSeparator() {\n return (\n <span aria-hidden className=\"text-border mx-0.5\">\n |\n </span>\n );\n}\n"],"names":[],"mappings":"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"}
|
package/dist/data/Icon.cjs
CHANGED
|
@@ -5,12 +5,12 @@ const utils = require("../lib/utils.cjs");
|
|
|
5
5
|
const size = require("../lib/size.cjs");
|
|
6
6
|
const useDensity = require("../hooks/use-density.cjs");
|
|
7
7
|
const TONE_CLASSES = {
|
|
8
|
-
emerald: "text-emerald-700 ring-emerald-200/80",
|
|
9
|
-
amber: "text-amber-700 ring-amber-200/80",
|
|
10
|
-
rose: "text-rose-700 ring-rose-200/80",
|
|
11
|
-
slate: "text-slate-700 ring-slate-200/80",
|
|
12
|
-
sky: "text-sky-700 ring-sky-200/80",
|
|
13
|
-
violet: "text-violet-700 ring-violet-200/80",
|
|
8
|
+
emerald: "text-emerald-700 ring-emerald-200/80 dark:text-emerald-400 dark:ring-emerald-500/30",
|
|
9
|
+
amber: "text-amber-700 ring-amber-200/80 dark:text-amber-400 dark:ring-amber-500/30",
|
|
10
|
+
rose: "text-rose-700 ring-rose-200/80 dark:text-rose-400 dark:ring-rose-500/30",
|
|
11
|
+
slate: "text-slate-700 ring-slate-200/80 dark:text-slate-300 dark:ring-slate-500/30",
|
|
12
|
+
sky: "text-sky-700 ring-sky-200/80 dark:text-sky-400 dark:ring-sky-500/30",
|
|
13
|
+
violet: "text-violet-700 ring-violet-200/80 dark:text-violet-400 dark:ring-violet-500/30",
|
|
14
14
|
neutral: "text-foreground ring-border"
|
|
15
15
|
};
|
|
16
16
|
const DEFAULT_PLAIN_ICON_SIZE = "1em";
|
|
@@ -115,7 +115,7 @@ function Icon({
|
|
|
115
115
|
"aria-label": title,
|
|
116
116
|
role: title ? "img" : void 0,
|
|
117
117
|
className: utils.cn(
|
|
118
|
-
"inline-flex items-center justify-center rounded-full bg-
|
|
118
|
+
"inline-flex items-center justify-center rounded-full bg-background shadow-sm ring-1 ring-inset",
|
|
119
119
|
TONE_CLASSES[tone],
|
|
120
120
|
className
|
|
121
121
|
),
|
package/dist/data/Icon.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Icon.cjs","sources":["../../src/data/Icon.tsx"],"sourcesContent":["import type { CSSProperties, ComponentType, ElementType, ReactNode } from \"react\";\nimport { cn } from \"../lib/utils\";\nimport { resolveSize, type SizeToken } from \"../lib/size\";\nimport { useDensityValue } from \"../hooks/use-density\";\n\n// LabelIconSpec is the icon a label may carry: an iconify/runtime name (resolved\n// via the fallback provider) or a fully-rendered node the caller supplies.\nexport type LabelIconSpec = string | ReactNode;\n\nexport type IconStyle = \"plain\" | \"badge\";\n\nexport type IconTone = \"emerald\" | \"amber\" | \"rose\" | \"slate\" | \"sky\" | \"violet\" | \"neutral\";\n\nexport type StaticIconComponent = ElementType;\n\ntype CommonIconProps = {\n /** Classes applied to the glyph or badge wrapper. */\n className?: string;\n /** Explicit glyph width. */\n width?: string | number;\n /** Explicit glyph height. */\n height?: string | number;\n /** CSS rotate value or degrees. */\n rotate?: string | number;\n /** Flip direction for imported glyphs. */\n flip?: string;\n /** Forward inline rendering semantics to imported glyphs. */\n inline?: boolean;\n /** Accessible title for the glyph. */\n title?: string;\n /**\n * Presentation style. `plain` (default) renders the icon inline.\n * `badge` wraps the icon in a circular chip (white background, ring, shadow)\n * sized by `size` — use in stage/approval cells so the chip scales with a\n * neighbouring avatar.\n */\n style?: IconStyle;\n /**\n * Named size token (xxs..xxl). Drives the badge diameter and glyph. The\n * glyph is always ~50% of the badge diameter so it scales consistently\n * across sizes. For `style=\"plain\"` it sets width/height when neither is\n * provided.\n */\n size?: SizeToken;\n /** Semantic color for `style=\"badge\"`. Ignored for plain icons. */\n tone?: IconTone;\n};\n\nexport type IconProps = CommonIconProps &\n (\n | {\n /** Imported static icon component. */\n icon: StaticIconComponent;\n name?: never;\n }\n | {\n /** Runtime icon name resolved by the fallback provider. */\n name: string;\n icon?: never;\n }\n );\n\nconst TONE_CLASSES: Record<IconTone, string> = {\n emerald: \"text-emerald-700 ring-emerald-200/80\",\n amber: \"text-amber-700 ring-amber-200/80\",\n rose: \"text-rose-700 ring-rose-200/80\",\n slate: \"text-slate-700 ring-slate-200/80\",\n sky: \"text-sky-700 ring-sky-200/80\",\n violet: \"text-violet-700 ring-violet-200/80\",\n neutral: \"text-foreground ring-border\",\n};\n\nconst DEFAULT_PLAIN_ICON_SIZE = \"1em\";\n\n/**\n * Optional secondary icon provider for user-supplied runtime names.\n * Built-in/default icons should pass an imported component via `icon`.\n */\nexport type FallbackIconProps = {\n /** Runtime icon name to resolve. */\n name?: string;\n /** Classes applied by Icon. */\n className?: string;\n /** Requested glyph size. */\n size?: string | number;\n /** Accessible label. */\n alt?: string;\n};\n\ntype FallbackIconComponent = ComponentType<FallbackIconProps>;\n\nlet fallbackIcon: FallbackIconComponent | null = null;\n\n/**\n * Register a secondary glyph provider. Pass the flanksource Icon/ResourceIcon\n * (or any compatible component) to resolve user-supplied runtime names.\n */\nexport function setFallbackIconProvider(component: FallbackIconComponent | null): void {\n fallbackIcon = component;\n}\n\nfunction renderImportedGlyph(\n ImportedIcon: StaticIconComponent,\n glyphWidth: number | string | undefined,\n glyphHeight: number | string | undefined,\n rotate: string | number | undefined,\n flip: string | undefined,\n inline: boolean | undefined,\n glyphClassName: string | undefined,\n title: string | undefined,\n): JSX.Element {\n const transform = [\n typeof rotate === \"number\" ? `rotate(${rotate}deg)` : typeof rotate === \"string\" ? rotate : \"\",\n flip === \"horizontal\" || flip === \"both\" ? \"scaleX(-1)\" : \"\",\n flip === \"vertical\" || flip === \"both\" ? \"scaleY(-1)\" : \"\",\n ]\n .filter(Boolean)\n .join(\" \");\n\n return (\n <ImportedIcon\n {...(glyphClassName ? { className: glyphClassName } : {})}\n {...(glyphWidth != null ? { width: glyphWidth } : {})}\n {...(glyphHeight != null ? { height: glyphHeight } : {})}\n {...(inline != null ? { \"aria-hidden\": !title } : {})}\n {...(title ? { title, role: \"img\" } : { \"aria-hidden\": true })}\n {...(transform ? { style: { transform } } : {})}\n />\n );\n}\n\nfunction renderRuntimeGlyph(\n name: string,\n glyphWidth: number | string | undefined,\n glyphHeight: number | string | undefined,\n glyphClassName: string | undefined,\n title: string | undefined,\n): JSX.Element {\n if (fallbackIcon) {\n const Fallback = fallbackIcon;\n const glyphSize = typeof glyphWidth === \"number\" ? glyphWidth : glyphHeight;\n return (\n <Fallback\n name={name}\n {...(glyphClassName ? { className: glyphClassName } : {})}\n {...(glyphSize != null ? { size: glyphSize } : {})}\n {...(title ? { alt: title } : {})}\n />\n );\n }\n\n return (\n <span\n className={cn(\n \"inline-flex shrink-0 items-center justify-center rounded-sm border border-dashed border-muted-foreground/50 text-[0.65em] leading-none text-muted-foreground\",\n glyphClassName,\n )}\n title={title ?? name}\n role={title ? \"img\" : undefined}\n aria-label={title}\n aria-hidden={title ? undefined : true}\n style={{\n width: glyphWidth,\n height: glyphHeight,\n }}\n >\n ?\n </span>\n );\n}\n\nexport function Icon({\n icon: ImportedIcon,\n name,\n className,\n width,\n height,\n rotate,\n flip,\n inline,\n title,\n style = \"plain\",\n size,\n tone = \"neutral\",\n}: IconProps) {\n const density = useDensityValue();\n const pxSize = size != null ? resolveSize(size, density) : undefined;\n const glyphSize = pxSize != null ? Math.max(8, Math.round(pxSize * 0.5)) : undefined;\n const defaultGlyphSize = style === \"badge\" ? glyphSize : (pxSize ?? DEFAULT_PLAIN_ICON_SIZE);\n const resolvedWidth = width ?? height ?? defaultGlyphSize;\n const resolvedHeight = height ?? resolvedWidth;\n\n const glyphClassName = cn(\n \"inline-block shrink-0 align-[-0.125em]\",\n style === \"plain\" ? className : undefined,\n );\n const glyphTitle = style === \"plain\" ? title : undefined;\n\n const renderedIcon = ImportedIcon\n ? renderImportedGlyph(\n ImportedIcon,\n resolvedWidth,\n resolvedHeight,\n rotate,\n flip,\n inline,\n glyphClassName,\n glyphTitle,\n )\n : renderRuntimeGlyph(name, resolvedWidth, resolvedHeight, glyphClassName, glyphTitle);\n\n if (style === \"plain\") {\n return renderedIcon;\n }\n\n const badgeStyle: CSSProperties | undefined =\n pxSize != null ? { width: pxSize, height: pxSize } : undefined;\n\n return (\n <span\n title={title}\n aria-label={title}\n role={title ? \"img\" : undefined}\n className={cn(\n \"inline-flex items-center justify-center rounded-full bg-white shadow-sm ring-1 ring-inset\",\n TONE_CLASSES[tone],\n className,\n )}\n style={badgeStyle}\n >\n {renderedIcon}\n </span>\n );\n}\n\n/**\n * LabelIcon renders a label's leading glyph from a {@link LabelIconSpec}: a\n * string is treated as a runtime icon name (resolved by the registered fallback\n * provider), any other ReactNode is rendered as-is. Returns null for an absent\n * or empty spec so callers can spread it unconditionally before a label.\n */\nexport function LabelIcon({\n icon,\n className,\n}: {\n icon?: LabelIconSpec;\n className?: string;\n}): JSX.Element | null {\n if (icon == null || icon === \"\" || icon === false) return null;\n if (typeof icon === \"string\") {\n return <Icon name={icon} className={cn(\"shrink-0\", className)} />;\n }\n return <>{icon}</>;\n}\n"],"names":["jsx","cn","size","useDensityValue","resolveSize"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"Icon.cjs","sources":["../../src/data/Icon.tsx"],"sourcesContent":["import type { CSSProperties, ComponentType, ElementType, ReactNode } from \"react\";\nimport { cn } from \"../lib/utils\";\nimport { resolveSize, type SizeToken } from \"../lib/size\";\nimport { useDensityValue } from \"../hooks/use-density\";\n\n// LabelIconSpec is the icon a label may carry: an iconify/runtime name (resolved\n// via the fallback provider) or a fully-rendered node the caller supplies.\nexport type LabelIconSpec = string | ReactNode;\n\nexport type IconStyle = \"plain\" | \"badge\";\n\nexport type IconTone = \"emerald\" | \"amber\" | \"rose\" | \"slate\" | \"sky\" | \"violet\" | \"neutral\";\n\nexport type StaticIconComponent = ElementType;\n\ntype CommonIconProps = {\n /** Classes applied to the glyph or badge wrapper. */\n className?: string;\n /** Explicit glyph width. */\n width?: string | number;\n /** Explicit glyph height. */\n height?: string | number;\n /** CSS rotate value or degrees. */\n rotate?: string | number;\n /** Flip direction for imported glyphs. */\n flip?: string;\n /** Forward inline rendering semantics to imported glyphs. */\n inline?: boolean;\n /** Accessible title for the glyph. */\n title?: string;\n /**\n * Presentation style. `plain` (default) renders the icon inline.\n * `badge` wraps the icon in a circular chip (white background, ring, shadow)\n * sized by `size` — use in stage/approval cells so the chip scales with a\n * neighbouring avatar.\n */\n style?: IconStyle;\n /**\n * Named size token (xxs..xxl). Drives the badge diameter and glyph. The\n * glyph is always ~50% of the badge diameter so it scales consistently\n * across sizes. For `style=\"plain\"` it sets width/height when neither is\n * provided.\n */\n size?: SizeToken;\n /** Semantic color for `style=\"badge\"`. Ignored for plain icons. */\n tone?: IconTone;\n};\n\nexport type IconProps = CommonIconProps &\n (\n | {\n /** Imported static icon component. */\n icon: StaticIconComponent;\n name?: never;\n }\n | {\n /** Runtime icon name resolved by the fallback provider. */\n name: string;\n icon?: never;\n }\n );\n\nconst TONE_CLASSES: Record<IconTone, string> = {\n emerald: \"text-emerald-700 ring-emerald-200/80 dark:text-emerald-400 dark:ring-emerald-500/30\",\n amber: \"text-amber-700 ring-amber-200/80 dark:text-amber-400 dark:ring-amber-500/30\",\n rose: \"text-rose-700 ring-rose-200/80 dark:text-rose-400 dark:ring-rose-500/30\",\n slate: \"text-slate-700 ring-slate-200/80 dark:text-slate-300 dark:ring-slate-500/30\",\n sky: \"text-sky-700 ring-sky-200/80 dark:text-sky-400 dark:ring-sky-500/30\",\n violet: \"text-violet-700 ring-violet-200/80 dark:text-violet-400 dark:ring-violet-500/30\",\n neutral: \"text-foreground ring-border\",\n};\n\nconst DEFAULT_PLAIN_ICON_SIZE = \"1em\";\n\n/**\n * Optional secondary icon provider for user-supplied runtime names.\n * Built-in/default icons should pass an imported component via `icon`.\n */\nexport type FallbackIconProps = {\n /** Runtime icon name to resolve. */\n name?: string;\n /** Classes applied by Icon. */\n className?: string;\n /** Requested glyph size. */\n size?: string | number;\n /** Accessible label. */\n alt?: string;\n};\n\ntype FallbackIconComponent = ComponentType<FallbackIconProps>;\n\nlet fallbackIcon: FallbackIconComponent | null = null;\n\n/**\n * Register a secondary glyph provider. Pass the flanksource Icon/ResourceIcon\n * (or any compatible component) to resolve user-supplied runtime names.\n */\nexport function setFallbackIconProvider(component: FallbackIconComponent | null): void {\n fallbackIcon = component;\n}\n\nfunction renderImportedGlyph(\n ImportedIcon: StaticIconComponent,\n glyphWidth: number | string | undefined,\n glyphHeight: number | string | undefined,\n rotate: string | number | undefined,\n flip: string | undefined,\n inline: boolean | undefined,\n glyphClassName: string | undefined,\n title: string | undefined,\n): JSX.Element {\n const transform = [\n typeof rotate === \"number\" ? `rotate(${rotate}deg)` : typeof rotate === \"string\" ? rotate : \"\",\n flip === \"horizontal\" || flip === \"both\" ? \"scaleX(-1)\" : \"\",\n flip === \"vertical\" || flip === \"both\" ? \"scaleY(-1)\" : \"\",\n ]\n .filter(Boolean)\n .join(\" \");\n\n return (\n <ImportedIcon\n {...(glyphClassName ? { className: glyphClassName } : {})}\n {...(glyphWidth != null ? { width: glyphWidth } : {})}\n {...(glyphHeight != null ? { height: glyphHeight } : {})}\n {...(inline != null ? { \"aria-hidden\": !title } : {})}\n {...(title ? { title, role: \"img\" } : { \"aria-hidden\": true })}\n {...(transform ? { style: { transform } } : {})}\n />\n );\n}\n\nfunction renderRuntimeGlyph(\n name: string,\n glyphWidth: number | string | undefined,\n glyphHeight: number | string | undefined,\n glyphClassName: string | undefined,\n title: string | undefined,\n): JSX.Element {\n if (fallbackIcon) {\n const Fallback = fallbackIcon;\n const glyphSize = typeof glyphWidth === \"number\" ? glyphWidth : glyphHeight;\n return (\n <Fallback\n name={name}\n {...(glyphClassName ? { className: glyphClassName } : {})}\n {...(glyphSize != null ? { size: glyphSize } : {})}\n {...(title ? { alt: title } : {})}\n />\n );\n }\n\n return (\n <span\n className={cn(\n \"inline-flex shrink-0 items-center justify-center rounded-sm border border-dashed border-muted-foreground/50 text-[0.65em] leading-none text-muted-foreground\",\n glyphClassName,\n )}\n title={title ?? name}\n role={title ? \"img\" : undefined}\n aria-label={title}\n aria-hidden={title ? undefined : true}\n style={{\n width: glyphWidth,\n height: glyphHeight,\n }}\n >\n ?\n </span>\n );\n}\n\nexport function Icon({\n icon: ImportedIcon,\n name,\n className,\n width,\n height,\n rotate,\n flip,\n inline,\n title,\n style = \"plain\",\n size,\n tone = \"neutral\",\n}: IconProps) {\n const density = useDensityValue();\n const pxSize = size != null ? resolveSize(size, density) : undefined;\n const glyphSize = pxSize != null ? Math.max(8, Math.round(pxSize * 0.5)) : undefined;\n const defaultGlyphSize = style === \"badge\" ? glyphSize : (pxSize ?? DEFAULT_PLAIN_ICON_SIZE);\n const resolvedWidth = width ?? height ?? defaultGlyphSize;\n const resolvedHeight = height ?? resolvedWidth;\n\n const glyphClassName = cn(\n \"inline-block shrink-0 align-[-0.125em]\",\n style === \"plain\" ? className : undefined,\n );\n const glyphTitle = style === \"plain\" ? title : undefined;\n\n const renderedIcon = ImportedIcon\n ? renderImportedGlyph(\n ImportedIcon,\n resolvedWidth,\n resolvedHeight,\n rotate,\n flip,\n inline,\n glyphClassName,\n glyphTitle,\n )\n : renderRuntimeGlyph(name, resolvedWidth, resolvedHeight, glyphClassName, glyphTitle);\n\n if (style === \"plain\") {\n return renderedIcon;\n }\n\n const badgeStyle: CSSProperties | undefined =\n pxSize != null ? { width: pxSize, height: pxSize } : undefined;\n\n return (\n <span\n title={title}\n aria-label={title}\n role={title ? \"img\" : undefined}\n className={cn(\n \"inline-flex items-center justify-center rounded-full bg-background shadow-sm ring-1 ring-inset\",\n TONE_CLASSES[tone],\n className,\n )}\n style={badgeStyle}\n >\n {renderedIcon}\n </span>\n );\n}\n\n/**\n * LabelIcon renders a label's leading glyph from a {@link LabelIconSpec}: a\n * string is treated as a runtime icon name (resolved by the registered fallback\n * provider), any other ReactNode is rendered as-is. Returns null for an absent\n * or empty spec so callers can spread it unconditionally before a label.\n */\nexport function LabelIcon({\n icon,\n className,\n}: {\n icon?: LabelIconSpec;\n className?: string;\n}): JSX.Element | null {\n if (icon == null || icon === \"\" || icon === false) return null;\n if (typeof icon === \"string\") {\n return <Icon name={icon} className={cn(\"shrink-0\", className)} />;\n }\n return <>{icon}</>;\n}\n"],"names":["jsx","cn","size","useDensityValue","resolveSize"],"mappings":"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"}
|
package/dist/data/Icon.js
CHANGED
|
@@ -3,12 +3,12 @@ import { cn } from "../lib/utils.js";
|
|
|
3
3
|
import { resolveSize } from "../lib/size.js";
|
|
4
4
|
import { useDensityValue } from "../hooks/use-density.js";
|
|
5
5
|
const TONE_CLASSES = {
|
|
6
|
-
emerald: "text-emerald-700 ring-emerald-200/80",
|
|
7
|
-
amber: "text-amber-700 ring-amber-200/80",
|
|
8
|
-
rose: "text-rose-700 ring-rose-200/80",
|
|
9
|
-
slate: "text-slate-700 ring-slate-200/80",
|
|
10
|
-
sky: "text-sky-700 ring-sky-200/80",
|
|
11
|
-
violet: "text-violet-700 ring-violet-200/80",
|
|
6
|
+
emerald: "text-emerald-700 ring-emerald-200/80 dark:text-emerald-400 dark:ring-emerald-500/30",
|
|
7
|
+
amber: "text-amber-700 ring-amber-200/80 dark:text-amber-400 dark:ring-amber-500/30",
|
|
8
|
+
rose: "text-rose-700 ring-rose-200/80 dark:text-rose-400 dark:ring-rose-500/30",
|
|
9
|
+
slate: "text-slate-700 ring-slate-200/80 dark:text-slate-300 dark:ring-slate-500/30",
|
|
10
|
+
sky: "text-sky-700 ring-sky-200/80 dark:text-sky-400 dark:ring-sky-500/30",
|
|
11
|
+
violet: "text-violet-700 ring-violet-200/80 dark:text-violet-400 dark:ring-violet-500/30",
|
|
12
12
|
neutral: "text-foreground ring-border"
|
|
13
13
|
};
|
|
14
14
|
const DEFAULT_PLAIN_ICON_SIZE = "1em";
|
|
@@ -113,7 +113,7 @@ function Icon({
|
|
|
113
113
|
"aria-label": title,
|
|
114
114
|
role: title ? "img" : void 0,
|
|
115
115
|
className: cn(
|
|
116
|
-
"inline-flex items-center justify-center rounded-full bg-
|
|
116
|
+
"inline-flex items-center justify-center rounded-full bg-background shadow-sm ring-1 ring-inset",
|
|
117
117
|
TONE_CLASSES[tone],
|
|
118
118
|
className
|
|
119
119
|
),
|
package/dist/data/Icon.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Icon.js","sources":["../../src/data/Icon.tsx"],"sourcesContent":["import type { CSSProperties, ComponentType, ElementType, ReactNode } from \"react\";\nimport { cn } from \"../lib/utils\";\nimport { resolveSize, type SizeToken } from \"../lib/size\";\nimport { useDensityValue } from \"../hooks/use-density\";\n\n// LabelIconSpec is the icon a label may carry: an iconify/runtime name (resolved\n// via the fallback provider) or a fully-rendered node the caller supplies.\nexport type LabelIconSpec = string | ReactNode;\n\nexport type IconStyle = \"plain\" | \"badge\";\n\nexport type IconTone = \"emerald\" | \"amber\" | \"rose\" | \"slate\" | \"sky\" | \"violet\" | \"neutral\";\n\nexport type StaticIconComponent = ElementType;\n\ntype CommonIconProps = {\n /** Classes applied to the glyph or badge wrapper. */\n className?: string;\n /** Explicit glyph width. */\n width?: string | number;\n /** Explicit glyph height. */\n height?: string | number;\n /** CSS rotate value or degrees. */\n rotate?: string | number;\n /** Flip direction for imported glyphs. */\n flip?: string;\n /** Forward inline rendering semantics to imported glyphs. */\n inline?: boolean;\n /** Accessible title for the glyph. */\n title?: string;\n /**\n * Presentation style. `plain` (default) renders the icon inline.\n * `badge` wraps the icon in a circular chip (white background, ring, shadow)\n * sized by `size` — use in stage/approval cells so the chip scales with a\n * neighbouring avatar.\n */\n style?: IconStyle;\n /**\n * Named size token (xxs..xxl). Drives the badge diameter and glyph. The\n * glyph is always ~50% of the badge diameter so it scales consistently\n * across sizes. For `style=\"plain\"` it sets width/height when neither is\n * provided.\n */\n size?: SizeToken;\n /** Semantic color for `style=\"badge\"`. Ignored for plain icons. */\n tone?: IconTone;\n};\n\nexport type IconProps = CommonIconProps &\n (\n | {\n /** Imported static icon component. */\n icon: StaticIconComponent;\n name?: never;\n }\n | {\n /** Runtime icon name resolved by the fallback provider. */\n name: string;\n icon?: never;\n }\n );\n\nconst TONE_CLASSES: Record<IconTone, string> = {\n emerald: \"text-emerald-700 ring-emerald-200/80\",\n amber: \"text-amber-700 ring-amber-200/80\",\n rose: \"text-rose-700 ring-rose-200/80\",\n slate: \"text-slate-700 ring-slate-200/80\",\n sky: \"text-sky-700 ring-sky-200/80\",\n violet: \"text-violet-700 ring-violet-200/80\",\n neutral: \"text-foreground ring-border\",\n};\n\nconst DEFAULT_PLAIN_ICON_SIZE = \"1em\";\n\n/**\n * Optional secondary icon provider for user-supplied runtime names.\n * Built-in/default icons should pass an imported component via `icon`.\n */\nexport type FallbackIconProps = {\n /** Runtime icon name to resolve. */\n name?: string;\n /** Classes applied by Icon. */\n className?: string;\n /** Requested glyph size. */\n size?: string | number;\n /** Accessible label. */\n alt?: string;\n};\n\ntype FallbackIconComponent = ComponentType<FallbackIconProps>;\n\nlet fallbackIcon: FallbackIconComponent | null = null;\n\n/**\n * Register a secondary glyph provider. Pass the flanksource Icon/ResourceIcon\n * (or any compatible component) to resolve user-supplied runtime names.\n */\nexport function setFallbackIconProvider(component: FallbackIconComponent | null): void {\n fallbackIcon = component;\n}\n\nfunction renderImportedGlyph(\n ImportedIcon: StaticIconComponent,\n glyphWidth: number | string | undefined,\n glyphHeight: number | string | undefined,\n rotate: string | number | undefined,\n flip: string | undefined,\n inline: boolean | undefined,\n glyphClassName: string | undefined,\n title: string | undefined,\n): JSX.Element {\n const transform = [\n typeof rotate === \"number\" ? `rotate(${rotate}deg)` : typeof rotate === \"string\" ? rotate : \"\",\n flip === \"horizontal\" || flip === \"both\" ? \"scaleX(-1)\" : \"\",\n flip === \"vertical\" || flip === \"both\" ? \"scaleY(-1)\" : \"\",\n ]\n .filter(Boolean)\n .join(\" \");\n\n return (\n <ImportedIcon\n {...(glyphClassName ? { className: glyphClassName } : {})}\n {...(glyphWidth != null ? { width: glyphWidth } : {})}\n {...(glyphHeight != null ? { height: glyphHeight } : {})}\n {...(inline != null ? { \"aria-hidden\": !title } : {})}\n {...(title ? { title, role: \"img\" } : { \"aria-hidden\": true })}\n {...(transform ? { style: { transform } } : {})}\n />\n );\n}\n\nfunction renderRuntimeGlyph(\n name: string,\n glyphWidth: number | string | undefined,\n glyphHeight: number | string | undefined,\n glyphClassName: string | undefined,\n title: string | undefined,\n): JSX.Element {\n if (fallbackIcon) {\n const Fallback = fallbackIcon;\n const glyphSize = typeof glyphWidth === \"number\" ? glyphWidth : glyphHeight;\n return (\n <Fallback\n name={name}\n {...(glyphClassName ? { className: glyphClassName } : {})}\n {...(glyphSize != null ? { size: glyphSize } : {})}\n {...(title ? { alt: title } : {})}\n />\n );\n }\n\n return (\n <span\n className={cn(\n \"inline-flex shrink-0 items-center justify-center rounded-sm border border-dashed border-muted-foreground/50 text-[0.65em] leading-none text-muted-foreground\",\n glyphClassName,\n )}\n title={title ?? name}\n role={title ? \"img\" : undefined}\n aria-label={title}\n aria-hidden={title ? undefined : true}\n style={{\n width: glyphWidth,\n height: glyphHeight,\n }}\n >\n ?\n </span>\n );\n}\n\nexport function Icon({\n icon: ImportedIcon,\n name,\n className,\n width,\n height,\n rotate,\n flip,\n inline,\n title,\n style = \"plain\",\n size,\n tone = \"neutral\",\n}: IconProps) {\n const density = useDensityValue();\n const pxSize = size != null ? resolveSize(size, density) : undefined;\n const glyphSize = pxSize != null ? Math.max(8, Math.round(pxSize * 0.5)) : undefined;\n const defaultGlyphSize = style === \"badge\" ? glyphSize : (pxSize ?? DEFAULT_PLAIN_ICON_SIZE);\n const resolvedWidth = width ?? height ?? defaultGlyphSize;\n const resolvedHeight = height ?? resolvedWidth;\n\n const glyphClassName = cn(\n \"inline-block shrink-0 align-[-0.125em]\",\n style === \"plain\" ? className : undefined,\n );\n const glyphTitle = style === \"plain\" ? title : undefined;\n\n const renderedIcon = ImportedIcon\n ? renderImportedGlyph(\n ImportedIcon,\n resolvedWidth,\n resolvedHeight,\n rotate,\n flip,\n inline,\n glyphClassName,\n glyphTitle,\n )\n : renderRuntimeGlyph(name, resolvedWidth, resolvedHeight, glyphClassName, glyphTitle);\n\n if (style === \"plain\") {\n return renderedIcon;\n }\n\n const badgeStyle: CSSProperties | undefined =\n pxSize != null ? { width: pxSize, height: pxSize } : undefined;\n\n return (\n <span\n title={title}\n aria-label={title}\n role={title ? \"img\" : undefined}\n className={cn(\n \"inline-flex items-center justify-center rounded-full bg-white shadow-sm ring-1 ring-inset\",\n TONE_CLASSES[tone],\n className,\n )}\n style={badgeStyle}\n >\n {renderedIcon}\n </span>\n );\n}\n\n/**\n * LabelIcon renders a label's leading glyph from a {@link LabelIconSpec}: a\n * string is treated as a runtime icon name (resolved by the registered fallback\n * provider), any other ReactNode is rendered as-is. Returns null for an absent\n * or empty spec so callers can spread it unconditionally before a label.\n */\nexport function LabelIcon({\n icon,\n className,\n}: {\n icon?: LabelIconSpec;\n className?: string;\n}): JSX.Element | null {\n if (icon == null || icon === \"\" || icon === false) return null;\n if (typeof icon === \"string\") {\n return <Icon name={icon} className={cn(\"shrink-0\", className)} />;\n }\n return <>{icon}</>;\n}\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"Icon.js","sources":["../../src/data/Icon.tsx"],"sourcesContent":["import type { CSSProperties, ComponentType, ElementType, ReactNode } from \"react\";\nimport { cn } from \"../lib/utils\";\nimport { resolveSize, type SizeToken } from \"../lib/size\";\nimport { useDensityValue } from \"../hooks/use-density\";\n\n// LabelIconSpec is the icon a label may carry: an iconify/runtime name (resolved\n// via the fallback provider) or a fully-rendered node the caller supplies.\nexport type LabelIconSpec = string | ReactNode;\n\nexport type IconStyle = \"plain\" | \"badge\";\n\nexport type IconTone = \"emerald\" | \"amber\" | \"rose\" | \"slate\" | \"sky\" | \"violet\" | \"neutral\";\n\nexport type StaticIconComponent = ElementType;\n\ntype CommonIconProps = {\n /** Classes applied to the glyph or badge wrapper. */\n className?: string;\n /** Explicit glyph width. */\n width?: string | number;\n /** Explicit glyph height. */\n height?: string | number;\n /** CSS rotate value or degrees. */\n rotate?: string | number;\n /** Flip direction for imported glyphs. */\n flip?: string;\n /** Forward inline rendering semantics to imported glyphs. */\n inline?: boolean;\n /** Accessible title for the glyph. */\n title?: string;\n /**\n * Presentation style. `plain` (default) renders the icon inline.\n * `badge` wraps the icon in a circular chip (white background, ring, shadow)\n * sized by `size` — use in stage/approval cells so the chip scales with a\n * neighbouring avatar.\n */\n style?: IconStyle;\n /**\n * Named size token (xxs..xxl). Drives the badge diameter and glyph. The\n * glyph is always ~50% of the badge diameter so it scales consistently\n * across sizes. For `style=\"plain\"` it sets width/height when neither is\n * provided.\n */\n size?: SizeToken;\n /** Semantic color for `style=\"badge\"`. Ignored for plain icons. */\n tone?: IconTone;\n};\n\nexport type IconProps = CommonIconProps &\n (\n | {\n /** Imported static icon component. */\n icon: StaticIconComponent;\n name?: never;\n }\n | {\n /** Runtime icon name resolved by the fallback provider. */\n name: string;\n icon?: never;\n }\n );\n\nconst TONE_CLASSES: Record<IconTone, string> = {\n emerald: \"text-emerald-700 ring-emerald-200/80 dark:text-emerald-400 dark:ring-emerald-500/30\",\n amber: \"text-amber-700 ring-amber-200/80 dark:text-amber-400 dark:ring-amber-500/30\",\n rose: \"text-rose-700 ring-rose-200/80 dark:text-rose-400 dark:ring-rose-500/30\",\n slate: \"text-slate-700 ring-slate-200/80 dark:text-slate-300 dark:ring-slate-500/30\",\n sky: \"text-sky-700 ring-sky-200/80 dark:text-sky-400 dark:ring-sky-500/30\",\n violet: \"text-violet-700 ring-violet-200/80 dark:text-violet-400 dark:ring-violet-500/30\",\n neutral: \"text-foreground ring-border\",\n};\n\nconst DEFAULT_PLAIN_ICON_SIZE = \"1em\";\n\n/**\n * Optional secondary icon provider for user-supplied runtime names.\n * Built-in/default icons should pass an imported component via `icon`.\n */\nexport type FallbackIconProps = {\n /** Runtime icon name to resolve. */\n name?: string;\n /** Classes applied by Icon. */\n className?: string;\n /** Requested glyph size. */\n size?: string | number;\n /** Accessible label. */\n alt?: string;\n};\n\ntype FallbackIconComponent = ComponentType<FallbackIconProps>;\n\nlet fallbackIcon: FallbackIconComponent | null = null;\n\n/**\n * Register a secondary glyph provider. Pass the flanksource Icon/ResourceIcon\n * (or any compatible component) to resolve user-supplied runtime names.\n */\nexport function setFallbackIconProvider(component: FallbackIconComponent | null): void {\n fallbackIcon = component;\n}\n\nfunction renderImportedGlyph(\n ImportedIcon: StaticIconComponent,\n glyphWidth: number | string | undefined,\n glyphHeight: number | string | undefined,\n rotate: string | number | undefined,\n flip: string | undefined,\n inline: boolean | undefined,\n glyphClassName: string | undefined,\n title: string | undefined,\n): JSX.Element {\n const transform = [\n typeof rotate === \"number\" ? `rotate(${rotate}deg)` : typeof rotate === \"string\" ? rotate : \"\",\n flip === \"horizontal\" || flip === \"both\" ? \"scaleX(-1)\" : \"\",\n flip === \"vertical\" || flip === \"both\" ? \"scaleY(-1)\" : \"\",\n ]\n .filter(Boolean)\n .join(\" \");\n\n return (\n <ImportedIcon\n {...(glyphClassName ? { className: glyphClassName } : {})}\n {...(glyphWidth != null ? { width: glyphWidth } : {})}\n {...(glyphHeight != null ? { height: glyphHeight } : {})}\n {...(inline != null ? { \"aria-hidden\": !title } : {})}\n {...(title ? { title, role: \"img\" } : { \"aria-hidden\": true })}\n {...(transform ? { style: { transform } } : {})}\n />\n );\n}\n\nfunction renderRuntimeGlyph(\n name: string,\n glyphWidth: number | string | undefined,\n glyphHeight: number | string | undefined,\n glyphClassName: string | undefined,\n title: string | undefined,\n): JSX.Element {\n if (fallbackIcon) {\n const Fallback = fallbackIcon;\n const glyphSize = typeof glyphWidth === \"number\" ? glyphWidth : glyphHeight;\n return (\n <Fallback\n name={name}\n {...(glyphClassName ? { className: glyphClassName } : {})}\n {...(glyphSize != null ? { size: glyphSize } : {})}\n {...(title ? { alt: title } : {})}\n />\n );\n }\n\n return (\n <span\n className={cn(\n \"inline-flex shrink-0 items-center justify-center rounded-sm border border-dashed border-muted-foreground/50 text-[0.65em] leading-none text-muted-foreground\",\n glyphClassName,\n )}\n title={title ?? name}\n role={title ? \"img\" : undefined}\n aria-label={title}\n aria-hidden={title ? undefined : true}\n style={{\n width: glyphWidth,\n height: glyphHeight,\n }}\n >\n ?\n </span>\n );\n}\n\nexport function Icon({\n icon: ImportedIcon,\n name,\n className,\n width,\n height,\n rotate,\n flip,\n inline,\n title,\n style = \"plain\",\n size,\n tone = \"neutral\",\n}: IconProps) {\n const density = useDensityValue();\n const pxSize = size != null ? resolveSize(size, density) : undefined;\n const glyphSize = pxSize != null ? Math.max(8, Math.round(pxSize * 0.5)) : undefined;\n const defaultGlyphSize = style === \"badge\" ? glyphSize : (pxSize ?? DEFAULT_PLAIN_ICON_SIZE);\n const resolvedWidth = width ?? height ?? defaultGlyphSize;\n const resolvedHeight = height ?? resolvedWidth;\n\n const glyphClassName = cn(\n \"inline-block shrink-0 align-[-0.125em]\",\n style === \"plain\" ? className : undefined,\n );\n const glyphTitle = style === \"plain\" ? title : undefined;\n\n const renderedIcon = ImportedIcon\n ? renderImportedGlyph(\n ImportedIcon,\n resolvedWidth,\n resolvedHeight,\n rotate,\n flip,\n inline,\n glyphClassName,\n glyphTitle,\n )\n : renderRuntimeGlyph(name, resolvedWidth, resolvedHeight, glyphClassName, glyphTitle);\n\n if (style === \"plain\") {\n return renderedIcon;\n }\n\n const badgeStyle: CSSProperties | undefined =\n pxSize != null ? { width: pxSize, height: pxSize } : undefined;\n\n return (\n <span\n title={title}\n aria-label={title}\n role={title ? \"img\" : undefined}\n className={cn(\n \"inline-flex items-center justify-center rounded-full bg-background shadow-sm ring-1 ring-inset\",\n TONE_CLASSES[tone],\n className,\n )}\n style={badgeStyle}\n >\n {renderedIcon}\n </span>\n );\n}\n\n/**\n * LabelIcon renders a label's leading glyph from a {@link LabelIconSpec}: a\n * string is treated as a runtime icon name (resolved by the registered fallback\n * provider), any other ReactNode is rendered as-is. Returns null for an absent\n * or empty spec so callers can spread it unconditionally before a label.\n */\nexport function LabelIcon({\n icon,\n className,\n}: {\n icon?: LabelIconSpec;\n className?: string;\n}): JSX.Element | null {\n if (icon == null || icon === \"\" || icon === false) return null;\n if (typeof icon === \"string\") {\n return <Icon name={icon} className={cn(\"shrink-0\", className)} />;\n }\n return <>{icon}</>;\n}\n"],"names":[],"mappings":"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"}
|
package/dist/data/LogDetails.cjs
CHANGED
|
@@ -2,9 +2,10 @@
|
|
|
2
2
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
3
3
|
const jsxRuntime = require("react/jsx-runtime");
|
|
4
4
|
const react = require("react");
|
|
5
|
-
const
|
|
5
|
+
const dataTableUtils = require("./data-table-utils.cjs");
|
|
6
6
|
const Properties = require("./Properties.cjs");
|
|
7
7
|
const TagList = require("./cells/TagList.cjs");
|
|
8
|
+
const tagUtils = require("./cells/tag-utils.cjs");
|
|
8
9
|
const propertiesUtils = require("./properties-utils.cjs");
|
|
9
10
|
const logUtils = require("./log-utils.cjs");
|
|
10
11
|
const UiCopy = require("../icons/components/UiCopy.cjs");
|
|
@@ -14,16 +15,6 @@ const UiZoomIn = require("../icons/components/UiZoomIn.cjs");
|
|
|
14
15
|
const UiZoomOut = require("../icons/components/UiZoomOut.cjs");
|
|
15
16
|
const TAGS_PATH = "details.tags";
|
|
16
17
|
const DETAIL_ROW_CLASS = "grid-cols-[fit-content(30ch)_minmax(0,1fr)]";
|
|
17
|
-
function renderLogDetails(row, context) {
|
|
18
|
-
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
19
|
-
LogDetails,
|
|
20
|
-
{
|
|
21
|
-
row,
|
|
22
|
-
filterActions: context.filterActionsByColumn,
|
|
23
|
-
columns: context.columns
|
|
24
|
-
}
|
|
25
|
-
);
|
|
26
|
-
}
|
|
27
18
|
function fieldColumnKey(path) {
|
|
28
19
|
if (!path.startsWith("details.") || path === TAGS_PATH) return void 0;
|
|
29
20
|
const rest = path.slice("details.".length);
|
|
@@ -50,7 +41,7 @@ function LogDetails({
|
|
|
50
41
|
const actions = filterActions[key];
|
|
51
42
|
const column = columnByKey.get(key);
|
|
52
43
|
if (!actions || !column) return void 0;
|
|
53
|
-
const token =
|
|
44
|
+
const token = dataTableUtils.getFilterTokens(row, column)[0];
|
|
54
45
|
return token ? { actions, token } : void 0;
|
|
55
46
|
};
|
|
56
47
|
const prefixActions = [
|
|
@@ -132,7 +123,7 @@ function LogDetails({
|
|
|
132
123
|
renderChildren: () => isTags ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
133
124
|
TagList.TagPropertiesList,
|
|
134
125
|
{
|
|
135
|
-
tags:
|
|
126
|
+
tags: tagUtils.normalizeTags(entryValue),
|
|
136
127
|
rowClassName: DETAIL_ROW_CLASS
|
|
137
128
|
}
|
|
138
129
|
) : /* @__PURE__ */ jsxRuntime.jsx(
|
|
@@ -275,5 +266,5 @@ function stripEmptyProperties(record) {
|
|
|
275
266
|
})
|
|
276
267
|
);
|
|
277
268
|
}
|
|
278
|
-
exports.
|
|
269
|
+
exports.LogDetails = LogDetails;
|
|
279
270
|
//# sourceMappingURL=LogDetails.cjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"LogDetails.cjs","sources":["../../src/data/LogDetails.tsx"],"sourcesContent":["import { useMemo, useState, type ReactNode } from \"react\";\nimport {\n getFilterTokens,\n type DataTableColumn,\n type DataTableRowDetailContext,\n} from \"./DataTable\";\nimport { Properties, type PropertiesAction, type PropertiesItem } from \"./Properties\";\nimport {\n TagActionsProvider,\n TagPropertiesList,\n type TagActionsContextValue,\n normalizeTags,\n} from \"./cells/TagList\";\nimport { formatPropertyLabel } from \"./properties-utils\";\nimport type { LogsTableRow } from \"./LogsTable\";\nimport { asRecord } from \"./log-utils\";\nimport { UiChevronDown, UiChevronRight, UiCopy, UiZoomIn, UiZoomOut } from \"../icons\";\n\nconst TAGS_PATH = \"details.tags\";\n\n// Key column shrinks to its content (no min/fixed width), never wider than 30ch.\nconst DETAIL_ROW_CLASS = \"grid-cols-[fit-content(30ch)_minmax(0,1fr)]\";\n\nexport function renderLogDetails(\n row: LogsTableRow,\n context: DataTableRowDetailContext<LogsTableRow>,\n): ReactNode {\n return (\n <LogDetails\n row={row}\n filterActions={context.filterActionsByColumn}\n columns={context.columns}\n />\n );\n}\n\n/**\n * Maps a top-level detail field path (`details.<columnKey>`) to its column key.\n * Returns undefined for nested paths and the tags array, which have their own\n * filter affordances.\n */\nfunction fieldColumnKey(path: string): string | undefined {\n if (!path.startsWith(\"details.\") || path === TAGS_PATH) return undefined;\n const rest = path.slice(\"details.\".length);\n return rest && !rest.includes(\".\") ? rest : undefined;\n}\n\nfunction LogDetails({\n row,\n filterActions,\n columns,\n}: {\n row: LogsTableRow;\n filterActions: Record<string, TagActionsContextValue>;\n columns: DataTableColumn<LogsTableRow>[];\n}) {\n const [openPaths, setOpenPaths] = useState<Record<string, boolean>>({});\n const setPathOpen = (path: string, open: boolean) => {\n setOpenPaths((current) => ({ ...current, [path]: open }));\n };\n const details = useMemo(() => buildProcessedLogDetails(row), [row]);\n\n const labelForPath = (path: string) => formatPropertyLabel(path.split(\".\").pop() ?? path);\n\n const columnByKey = useMemo(\n () => new Map(columns.map((column) => [column.key, column])),\n [columns],\n );\n\n // Include/exclude is wired only for fields whose column is a multi/nested-multi\n // (tristate) filter; other columns (high-cardinality text, number, timestamp)\n // don't honor multiFilters, so they get no filter actions. The toggle token\n // must match the column's filter token (e.g. a status column maps \"INFO\" to a\n // normalized status), so it is derived via getFilterTokens rather than the\n // displayed value.\n const fieldFilter = (\n path: string,\n ): { actions: TagActionsContextValue; token: string } | undefined => {\n const key = fieldColumnKey(path);\n if (!key) return undefined;\n const actions = filterActions[key];\n const column = columnByKey.get(key);\n if (!actions || !column) return undefined;\n const token = getFilterTokens(row, column)[0];\n return token ? { actions, token } : undefined;\n };\n\n const prefixActions: PropertiesAction<unknown>[] = [\n {\n id: \"expand\",\n icon: UiChevronRight,\n label: (key) => `Expand ${labelForPath(key)}`,\n visible: (_k, _v, item) => !!item.expandable,\n disabled: (_k, _v, item) => !!item.expanded,\n onClick: (_k, _v, item) => item.onToggle?.(true),\n },\n {\n id: \"collapse\",\n icon: UiChevronDown,\n label: (key) => `Collapse ${labelForPath(key)}`,\n visible: (_k, _v, item) => !!item.expandable,\n disabled: (_k, _v, item) => !item.expanded,\n onClick: (_k, _v, item) => item.onToggle?.(false),\n },\n {\n id: \"include\",\n icon: UiZoomIn,\n label: (key) => `Include ${labelForPath(key)}`,\n visible: (key) => !!fieldFilter(key),\n onClick: (key) => {\n const filter = fieldFilter(key);\n filter?.actions.toggleInclude(filter.token);\n },\n },\n {\n id: \"exclude\",\n icon: UiZoomOut,\n label: (key) => `Exclude ${labelForPath(key)}`,\n visible: (key) => !!fieldFilter(key),\n onClick: (key) => {\n const filter = fieldFilter(key);\n filter?.actions.toggleExclude(filter.token);\n },\n },\n ];\n\n // Copy sits immediately after the value (suffix), separate from the leading\n // expand/collapse/include/exclude controls.\n const suffixActions: PropertiesAction<unknown>[] = [\n {\n id: \"copy\",\n icon: UiCopy,\n label: (key) => `Copy ${labelForPath(key)}`,\n visible: (key) => key !== TAGS_PATH,\n onClick: (_k, value) => copyLogDetailsValue(value),\n },\n ];\n\n const renderLabel = (key: string) => labelForPath(key);\n const renderValue = (key: string, value: unknown, item: PropertiesItem<unknown>) => {\n if (key === TAGS_PATH) {\n const count = Array.isArray(value) ? value.length : 0;\n return <span className=\"font-mono text-muted-foreground\">[{count} tags]</span>;\n }\n return item.expandable ? <LogValueSummary value={value} /> : <LogScalarValue value={value} />;\n };\n\n const toItems = (value: unknown, path: string, depth: number): PropertiesItem<unknown>[] =>\n getValueEntries(value).map(([key, entryValue]) => {\n const entryPath = `${path}.${String(key)}`;\n const isTags = entryPath === TAGS_PATH;\n const expandable = isTags || isExpandableValue(entryValue);\n const open = openPaths[entryPath] ?? depth < 1;\n return {\n key: entryPath,\n value: entryValue,\n expandable,\n expanded: open,\n onToggle: (next) => setPathOpen(entryPath, next),\n renderChildren: () =>\n isTags ? (\n <TagPropertiesList\n tags={normalizeTags(entryValue as string[])}\n rowClassName={DETAIL_ROW_CLASS}\n />\n ) : (\n <Properties\n density=\"compact\"\n items={toItems(entryValue, entryPath, depth + 1)}\n renderLabel={renderLabel}\n renderValue={renderValue}\n prefixActions={prefixActions}\n suffixActions={suffixActions}\n rowClassName={DETAIL_ROW_CLASS}\n className=\"mt-density-1\"\n />\n ),\n };\n });\n\n const properties = (\n <Properties\n density=\"compact\"\n items={toItems(details, \"details\", 0)}\n renderLabel={renderLabel}\n renderValue={renderValue}\n prefixActions={prefixActions}\n suffixActions={suffixActions}\n rowClassName={DETAIL_ROW_CLASS}\n />\n );\n\n const tagActions = filterActions[\"tags\"];\n return (\n <div className=\"space-y-density-3 text-xs\">\n {tagActions ? (\n <TagActionsProvider value={tagActions}>{properties}</TagActionsProvider>\n ) : (\n properties\n )}\n </div>\n );\n}\n\nfunction LogValueSummary({ value }: { value: unknown }) {\n if (Array.isArray(value)) {\n return <span className=\"font-mono text-muted-foreground\">[{value.length} items]</span>;\n }\n const record = asRecord(value);\n if (record) {\n const count = Object.keys(record).length;\n return (\n <span className=\"font-mono text-muted-foreground\">\n {\"{ \"}\n {count} properties{\" }\"}\n </span>\n );\n }\n return <LogScalarValue value={value} />;\n}\n\nfunction LogScalarValue({ value }: { value: unknown }) {\n if (value === null || value === undefined) {\n return <span className=\"font-mono italic text-muted-foreground\">null</span>;\n }\n\n if (typeof value === \"string\") {\n return (\n <pre className=\"max-h-48 overflow-auto whitespace-pre-wrap break-words font-mono text-[11px] leading-relaxed text-foreground\">\n {value}\n </pre>\n );\n }\n\n if (typeof value === \"number\" || typeof value === \"boolean\") {\n return <span className=\"font-mono text-blue-700 dark:text-blue-400\">{String(value)}</span>;\n }\n\n return (\n <pre className=\"max-h-48 overflow-auto whitespace-pre-wrap break-words font-mono text-[11px] leading-relaxed text-foreground\">\n {stablePrettyString(value)}\n </pre>\n );\n}\n\nfunction getValueEntries(value: unknown): Array<[string | number, unknown]> {\n if (Array.isArray(value)) {\n return value.map((entry, index) => [index, entry]);\n }\n return Object.entries(asRecord(value) ?? {});\n}\n\nfunction isExpandableValue(value: unknown) {\n return getValueEntries(value).length > 0;\n}\n\nfunction stablePrettyString(value: unknown): string {\n if (typeof value === \"string\") return value;\n try {\n return JSON.stringify(value, null, 2);\n } catch {\n return String(value);\n }\n}\n\nfunction copyLogDetailsValue(value: unknown) {\n if (typeof navigator !== \"undefined\" && navigator.clipboard?.writeText) {\n Promise.resolve(navigator.clipboard.writeText(stablePrettyString(value))).catch(\n () => undefined,\n );\n }\n}\n\nfunction buildProcessedLogDetails(row: LogsTableRow): Record<string, unknown> {\n const attributes = buildProcessedLogAttributes(row);\n return stripEmptyProperties({\n timestamp: row.timestamp,\n level: row.level,\n pod: row.pod,\n logger: row.logger,\n thread: row.thread,\n message: row.message,\n tags: row.tags,\n ...(Object.keys(attributes).length > 0 ? { attributes } : {}),\n });\n}\n\nfunction buildProcessedLogAttributes(row: LogsTableRow): Record<string, unknown> {\n const attributes = {\n ...asRecord(row.raw),\n ...asRecord(row.parsedLine),\n };\n const hiddenKeys = new Set([\n \"@timestamp\",\n \"container\",\n \"event.dataset\",\n \"labels\",\n \"level\",\n \"line\",\n \"log.level\",\n \"log.logger\",\n \"logger\",\n \"message\",\n \"msg\",\n \"pod\",\n \"process.thread.name\",\n \"service\",\n \"service.name\",\n \"severity\",\n \"thread\",\n \"time\",\n \"timestamp\",\n ]);\n\n return stripEmptyProperties(\n Object.fromEntries(Object.entries(attributes).filter(([key]) => !hiddenKeys.has(key))),\n );\n}\n\nfunction stripEmptyProperties(record: Record<string, unknown>): Record<string, unknown> {\n return Object.fromEntries(\n Object.entries(record).filter(([, value]) => {\n if (value == null) return false;\n if (typeof value === \"string\") return value.trim().length > 0;\n if (Array.isArray(value)) return value.length > 0;\n return true;\n }),\n );\n}\n"],"names":["jsx","useState","useMemo","formatPropertyLabel","getFilterTokens","UiChevronRight","UiChevronDown","UiZoomIn","UiZoomOut","UiCopy","jsxs","TagPropertiesList","normalizeTags","Properties","TagActionsProvider","asRecord"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"LogDetails.cjs","sources":["../../src/data/LogDetails.tsx"],"sourcesContent":["import { useMemo, useState } from \"react\";\nimport type { DataTableColumn } from \"./DataTable\";\nimport { getFilterTokens } from \"./data-table-utils\";\nimport { Properties, type PropertiesAction, type PropertiesItem } from \"./Properties\";\nimport { TagActionsProvider, TagPropertiesList } from \"./cells/TagList\";\nimport { normalizeTags, type TagActionsContextValue } from \"./cells/tag-utils\";\nimport { formatPropertyLabel } from \"./properties-utils\";\nimport type { LogsTableRow } from \"./logs-normalize\";\nimport { asRecord } from \"./log-utils\";\nimport { UiChevronDown, UiChevronRight, UiCopy, UiZoomIn, UiZoomOut } from \"../icons\";\n\nconst TAGS_PATH = \"details.tags\";\n\n// Key column shrinks to its content (no min/fixed width), never wider than 30ch.\nconst DETAIL_ROW_CLASS = \"grid-cols-[fit-content(30ch)_minmax(0,1fr)]\";\n\n/**\n * Maps a top-level detail field path (`details.<columnKey>`) to its column key.\n * Returns undefined for nested paths and the tags array, which have their own\n * filter affordances.\n */\nfunction fieldColumnKey(path: string): string | undefined {\n if (!path.startsWith(\"details.\") || path === TAGS_PATH) return undefined;\n const rest = path.slice(\"details.\".length);\n return rest && !rest.includes(\".\") ? rest : undefined;\n}\n\nexport function LogDetails({\n row,\n filterActions,\n columns,\n}: {\n row: LogsTableRow;\n filterActions: Record<string, TagActionsContextValue>;\n columns: DataTableColumn<LogsTableRow>[];\n}) {\n const [openPaths, setOpenPaths] = useState<Record<string, boolean>>({});\n const setPathOpen = (path: string, open: boolean) => {\n setOpenPaths((current) => ({ ...current, [path]: open }));\n };\n const details = useMemo(() => buildProcessedLogDetails(row), [row]);\n\n const labelForPath = (path: string) => formatPropertyLabel(path.split(\".\").pop() ?? path);\n\n const columnByKey = useMemo(\n () => new Map(columns.map((column) => [column.key, column])),\n [columns],\n );\n\n // Include/exclude is wired only for fields whose column is a multi/nested-multi\n // (tristate) filter; other columns (high-cardinality text, number, timestamp)\n // don't honor multiFilters, so they get no filter actions. The toggle token\n // must match the column's filter token (e.g. a status column maps \"INFO\" to a\n // normalized status), so it is derived via getFilterTokens rather than the\n // displayed value.\n const fieldFilter = (\n path: string,\n ): { actions: TagActionsContextValue; token: string } | undefined => {\n const key = fieldColumnKey(path);\n if (!key) return undefined;\n const actions = filterActions[key];\n const column = columnByKey.get(key);\n if (!actions || !column) return undefined;\n const token = getFilterTokens(row, column)[0];\n return token ? { actions, token } : undefined;\n };\n\n const prefixActions: PropertiesAction<unknown>[] = [\n {\n id: \"expand\",\n icon: UiChevronRight,\n label: (key) => `Expand ${labelForPath(key)}`,\n visible: (_k, _v, item) => !!item.expandable,\n disabled: (_k, _v, item) => !!item.expanded,\n onClick: (_k, _v, item) => item.onToggle?.(true),\n },\n {\n id: \"collapse\",\n icon: UiChevronDown,\n label: (key) => `Collapse ${labelForPath(key)}`,\n visible: (_k, _v, item) => !!item.expandable,\n disabled: (_k, _v, item) => !item.expanded,\n onClick: (_k, _v, item) => item.onToggle?.(false),\n },\n {\n id: \"include\",\n icon: UiZoomIn,\n label: (key) => `Include ${labelForPath(key)}`,\n visible: (key) => !!fieldFilter(key),\n onClick: (key) => {\n const filter = fieldFilter(key);\n filter?.actions.toggleInclude(filter.token);\n },\n },\n {\n id: \"exclude\",\n icon: UiZoomOut,\n label: (key) => `Exclude ${labelForPath(key)}`,\n visible: (key) => !!fieldFilter(key),\n onClick: (key) => {\n const filter = fieldFilter(key);\n filter?.actions.toggleExclude(filter.token);\n },\n },\n ];\n\n // Copy sits immediately after the value (suffix), separate from the leading\n // expand/collapse/include/exclude controls.\n const suffixActions: PropertiesAction<unknown>[] = [\n {\n id: \"copy\",\n icon: UiCopy,\n label: (key) => `Copy ${labelForPath(key)}`,\n visible: (key) => key !== TAGS_PATH,\n onClick: (_k, value) => copyLogDetailsValue(value),\n },\n ];\n\n const renderLabel = (key: string) => labelForPath(key);\n const renderValue = (key: string, value: unknown, item: PropertiesItem<unknown>) => {\n if (key === TAGS_PATH) {\n const count = Array.isArray(value) ? value.length : 0;\n return <span className=\"font-mono text-muted-foreground\">[{count} tags]</span>;\n }\n return item.expandable ? <LogValueSummary value={value} /> : <LogScalarValue value={value} />;\n };\n\n const toItems = (value: unknown, path: string, depth: number): PropertiesItem<unknown>[] =>\n getValueEntries(value).map(([key, entryValue]) => {\n const entryPath = `${path}.${String(key)}`;\n const isTags = entryPath === TAGS_PATH;\n const expandable = isTags || isExpandableValue(entryValue);\n const open = openPaths[entryPath] ?? depth < 1;\n return {\n key: entryPath,\n value: entryValue,\n expandable,\n expanded: open,\n onToggle: (next) => setPathOpen(entryPath, next),\n renderChildren: () =>\n isTags ? (\n <TagPropertiesList\n tags={normalizeTags(entryValue as string[])}\n rowClassName={DETAIL_ROW_CLASS}\n />\n ) : (\n <Properties\n density=\"compact\"\n items={toItems(entryValue, entryPath, depth + 1)}\n renderLabel={renderLabel}\n renderValue={renderValue}\n prefixActions={prefixActions}\n suffixActions={suffixActions}\n rowClassName={DETAIL_ROW_CLASS}\n className=\"mt-density-1\"\n />\n ),\n };\n });\n\n const properties = (\n <Properties\n density=\"compact\"\n items={toItems(details, \"details\", 0)}\n renderLabel={renderLabel}\n renderValue={renderValue}\n prefixActions={prefixActions}\n suffixActions={suffixActions}\n rowClassName={DETAIL_ROW_CLASS}\n />\n );\n\n const tagActions = filterActions[\"tags\"];\n return (\n <div className=\"space-y-density-3 text-xs\">\n {tagActions ? (\n <TagActionsProvider value={tagActions}>{properties}</TagActionsProvider>\n ) : (\n properties\n )}\n </div>\n );\n}\n\nfunction LogValueSummary({ value }: { value: unknown }) {\n if (Array.isArray(value)) {\n return <span className=\"font-mono text-muted-foreground\">[{value.length} items]</span>;\n }\n const record = asRecord(value);\n if (record) {\n const count = Object.keys(record).length;\n return (\n <span className=\"font-mono text-muted-foreground\">\n {\"{ \"}\n {count} properties{\" }\"}\n </span>\n );\n }\n return <LogScalarValue value={value} />;\n}\n\nfunction LogScalarValue({ value }: { value: unknown }) {\n if (value === null || value === undefined) {\n return <span className=\"font-mono italic text-muted-foreground\">null</span>;\n }\n\n if (typeof value === \"string\") {\n return (\n <pre className=\"max-h-48 overflow-auto whitespace-pre-wrap break-words font-mono text-[11px] leading-relaxed text-foreground\">\n {value}\n </pre>\n );\n }\n\n if (typeof value === \"number\" || typeof value === \"boolean\") {\n return <span className=\"font-mono text-blue-700 dark:text-blue-400\">{String(value)}</span>;\n }\n\n return (\n <pre className=\"max-h-48 overflow-auto whitespace-pre-wrap break-words font-mono text-[11px] leading-relaxed text-foreground\">\n {stablePrettyString(value)}\n </pre>\n );\n}\n\nfunction getValueEntries(value: unknown): Array<[string | number, unknown]> {\n if (Array.isArray(value)) {\n return value.map((entry, index) => [index, entry]);\n }\n return Object.entries(asRecord(value) ?? {});\n}\n\nfunction isExpandableValue(value: unknown) {\n return getValueEntries(value).length > 0;\n}\n\nfunction stablePrettyString(value: unknown): string {\n if (typeof value === \"string\") return value;\n try {\n return JSON.stringify(value, null, 2);\n } catch {\n return String(value);\n }\n}\n\nfunction copyLogDetailsValue(value: unknown) {\n if (typeof navigator !== \"undefined\" && navigator.clipboard?.writeText) {\n Promise.resolve(navigator.clipboard.writeText(stablePrettyString(value))).catch(\n () => undefined,\n );\n }\n}\n\nfunction buildProcessedLogDetails(row: LogsTableRow): Record<string, unknown> {\n const attributes = buildProcessedLogAttributes(row);\n return stripEmptyProperties({\n timestamp: row.timestamp,\n level: row.level,\n pod: row.pod,\n logger: row.logger,\n thread: row.thread,\n message: row.message,\n tags: row.tags,\n ...(Object.keys(attributes).length > 0 ? { attributes } : {}),\n });\n}\n\nfunction buildProcessedLogAttributes(row: LogsTableRow): Record<string, unknown> {\n const attributes = {\n ...asRecord(row.raw),\n ...asRecord(row.parsedLine),\n };\n const hiddenKeys = new Set([\n \"@timestamp\",\n \"container\",\n \"event.dataset\",\n \"labels\",\n \"level\",\n \"line\",\n \"log.level\",\n \"log.logger\",\n \"logger\",\n \"message\",\n \"msg\",\n \"pod\",\n \"process.thread.name\",\n \"service\",\n \"service.name\",\n \"severity\",\n \"thread\",\n \"time\",\n \"timestamp\",\n ]);\n\n return stripEmptyProperties(\n Object.fromEntries(Object.entries(attributes).filter(([key]) => !hiddenKeys.has(key))),\n );\n}\n\nfunction stripEmptyProperties(record: Record<string, unknown>): Record<string, unknown> {\n return Object.fromEntries(\n Object.entries(record).filter(([, value]) => {\n if (value == null) return false;\n if (typeof value === \"string\") return value.trim().length > 0;\n if (Array.isArray(value)) return value.length > 0;\n return true;\n }),\n );\n}\n"],"names":["useState","useMemo","formatPropertyLabel","getFilterTokens","UiChevronRight","UiChevronDown","UiZoomIn","UiZoomOut","UiCopy","jsxs","jsx","TagPropertiesList","normalizeTags","Properties","TagActionsProvider","asRecord"],"mappings":"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"}
|
|
@@ -1,5 +1,9 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import { LogsTableRow } from './
|
|
4
|
-
export declare function
|
|
1
|
+
import { DataTableColumn } from './DataTable';
|
|
2
|
+
import { TagActionsContextValue } from './cells/tag-utils';
|
|
3
|
+
import { LogsTableRow } from './logs-normalize';
|
|
4
|
+
export declare function LogDetails({ row, filterActions, columns, }: {
|
|
5
|
+
row: LogsTableRow;
|
|
6
|
+
filterActions: Record<string, TagActionsContextValue>;
|
|
7
|
+
columns: DataTableColumn<LogsTableRow>[];
|
|
8
|
+
}): import("react/jsx-runtime").JSX.Element;
|
|
5
9
|
//# sourceMappingURL=LogDetails.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"LogDetails.d.ts","sourceRoot":"","sources":["../../src/data/LogDetails.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"LogDetails.d.ts","sourceRoot":"","sources":["../../src/data/LogDetails.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAInD,OAAO,EAAiB,KAAK,sBAAsB,EAAE,MAAM,mBAAmB,CAAC;AAE/E,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAoBrD,wBAAgB,UAAU,CAAC,EACzB,GAAG,EACH,aAAa,EACb,OAAO,GACR,EAAE;IACD,GAAG,EAAE,YAAY,CAAC;IAClB,aAAa,EAAE,MAAM,CAAC,MAAM,EAAE,sBAAsB,CAAC,CAAC;IACtD,OAAO,EAAE,eAAe,CAAC,YAAY,CAAC,EAAE,CAAC;CAC1C,2CAmJA"}
|
package/dist/data/LogDetails.js
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
2
2
|
import { useState, useMemo } from "react";
|
|
3
|
-
import { getFilterTokens } from "./
|
|
3
|
+
import { getFilterTokens } from "./data-table-utils.js";
|
|
4
4
|
import { Properties } from "./Properties.js";
|
|
5
|
-
import { TagActionsProvider, TagPropertiesList
|
|
5
|
+
import { TagActionsProvider, TagPropertiesList } from "./cells/TagList.js";
|
|
6
|
+
import { normalizeTags } from "./cells/tag-utils.js";
|
|
6
7
|
import { formatPropertyLabel } from "./properties-utils.js";
|
|
7
8
|
import { asRecord } from "./log-utils.js";
|
|
8
9
|
import { UiCopy } from "../icons/components/UiCopy.js";
|
|
@@ -12,16 +13,6 @@ import { UiZoomIn } from "../icons/components/UiZoomIn.js";
|
|
|
12
13
|
import { UiZoomOut } from "../icons/components/UiZoomOut.js";
|
|
13
14
|
const TAGS_PATH = "details.tags";
|
|
14
15
|
const DETAIL_ROW_CLASS = "grid-cols-[fit-content(30ch)_minmax(0,1fr)]";
|
|
15
|
-
function renderLogDetails(row, context) {
|
|
16
|
-
return /* @__PURE__ */ jsx(
|
|
17
|
-
LogDetails,
|
|
18
|
-
{
|
|
19
|
-
row,
|
|
20
|
-
filterActions: context.filterActionsByColumn,
|
|
21
|
-
columns: context.columns
|
|
22
|
-
}
|
|
23
|
-
);
|
|
24
|
-
}
|
|
25
16
|
function fieldColumnKey(path) {
|
|
26
17
|
if (!path.startsWith("details.") || path === TAGS_PATH) return void 0;
|
|
27
18
|
const rest = path.slice("details.".length);
|
|
@@ -274,6 +265,6 @@ function stripEmptyProperties(record) {
|
|
|
274
265
|
);
|
|
275
266
|
}
|
|
276
267
|
export {
|
|
277
|
-
|
|
268
|
+
LogDetails
|
|
278
269
|
};
|
|
279
270
|
//# sourceMappingURL=LogDetails.js.map
|