@flanksource/clicky-ui 0.3.30 → 0.3.32

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.
Files changed (157) hide show
  1. package/dist/comments/CommentCard.cjs +156 -273
  2. package/dist/comments/CommentCard.cjs.map +1 -1
  3. package/dist/comments/CommentCard.d.ts +5 -1
  4. package/dist/comments/CommentCard.d.ts.map +1 -1
  5. package/dist/comments/CommentCard.js +151 -268
  6. package/dist/comments/CommentCard.js.map +1 -1
  7. package/dist/comments/CommentCardParts.cjs +115 -0
  8. package/dist/comments/CommentCardParts.cjs.map +1 -0
  9. package/dist/comments/CommentCardParts.d.ts +21 -0
  10. package/dist/comments/CommentCardParts.d.ts.map +1 -0
  11. package/dist/comments/CommentCardParts.js +115 -0
  12. package/dist/comments/CommentCardParts.js.map +1 -0
  13. package/dist/comments/CommentProvider.cjs +3 -0
  14. package/dist/comments/CommentProvider.cjs.map +1 -1
  15. package/dist/comments/CommentProvider.d.ts +1 -1
  16. package/dist/comments/CommentProvider.d.ts.map +1 -1
  17. package/dist/comments/CommentProvider.js +3 -0
  18. package/dist/comments/CommentProvider.js.map +1 -1
  19. package/dist/comments/CommentSidePanel.cjs +55 -22
  20. package/dist/comments/CommentSidePanel.cjs.map +1 -1
  21. package/dist/comments/CommentSidePanel.d.ts +3 -1
  22. package/dist/comments/CommentSidePanel.d.ts.map +1 -1
  23. package/dist/comments/CommentSidePanel.js +56 -23
  24. package/dist/comments/CommentSidePanel.js.map +1 -1
  25. package/dist/comments/CommentThread.cjs +2 -0
  26. package/dist/comments/CommentThread.cjs.map +1 -1
  27. package/dist/comments/CommentThread.d.ts +2 -1
  28. package/dist/comments/CommentThread.d.ts.map +1 -1
  29. package/dist/comments/CommentThread.js +2 -0
  30. package/dist/comments/CommentThread.js.map +1 -1
  31. package/dist/comments/CommentThreadList.cjs +52 -34
  32. package/dist/comments/CommentThreadList.cjs.map +1 -1
  33. package/dist/comments/CommentThreadList.d.ts +5 -2
  34. package/dist/comments/CommentThreadList.d.ts.map +1 -1
  35. package/dist/comments/CommentThreadList.js +52 -34
  36. package/dist/comments/CommentThreadList.js.map +1 -1
  37. package/dist/comments/comment-types.cjs +16 -4
  38. package/dist/comments/comment-types.cjs.map +1 -1
  39. package/dist/comments/comment-types.d.ts +11 -1
  40. package/dist/comments/comment-types.d.ts.map +1 -1
  41. package/dist/comments/comment-types.js +16 -4
  42. package/dist/comments/comment-types.js.map +1 -1
  43. package/dist/comments/comment-utils.cjs +31 -1
  44. package/dist/comments/comment-utils.cjs.map +1 -1
  45. package/dist/comments/comment-utils.d.ts +9 -2
  46. package/dist/comments/comment-utils.d.ts.map +1 -1
  47. package/dist/comments/comment-utils.js +31 -1
  48. package/dist/comments/comment-utils.js.map +1 -1
  49. package/dist/comments.cjs +3 -0
  50. package/dist/comments.cjs.map +1 -1
  51. package/dist/comments.js +4 -1
  52. package/dist/components/ComboboxMenu.cjs +4 -1
  53. package/dist/components/ComboboxMenu.cjs.map +1 -1
  54. package/dist/components/ComboboxMenu.d.ts.map +1 -1
  55. package/dist/components/ComboboxMenu.js +5 -2
  56. package/dist/components/ComboboxMenu.js.map +1 -1
  57. package/dist/components/ComboboxTags.cjs +5 -1
  58. package/dist/components/ComboboxTags.cjs.map +1 -1
  59. package/dist/components/ComboboxTags.d.ts.map +1 -1
  60. package/dist/components/ComboboxTags.js +6 -2
  61. package/dist/components/ComboboxTags.js.map +1 -1
  62. package/dist/components/ConnectionLoggingPolicy.cjs +24 -35
  63. package/dist/components/ConnectionLoggingPolicy.cjs.map +1 -1
  64. package/dist/components/ConnectionLoggingPolicy.d.ts.map +1 -1
  65. package/dist/components/ConnectionLoggingPolicy.js +24 -35
  66. package/dist/components/ConnectionLoggingPolicy.js.map +1 -1
  67. package/dist/components/MultiSelect.cjs.map +1 -1
  68. package/dist/components/MultiSelect.d.ts +7 -0
  69. package/dist/components/MultiSelect.d.ts.map +1 -1
  70. package/dist/components/MultiSelect.js.map +1 -1
  71. package/dist/components/filter-bar-multi.cjs +10 -1
  72. package/dist/components/filter-bar-multi.cjs.map +1 -1
  73. package/dist/components/filter-bar-multi.d.ts.map +1 -1
  74. package/dist/components/filter-bar-multi.js +11 -2
  75. package/dist/components/filter-bar-multi.js.map +1 -1
  76. package/dist/data/ai/SessionViewer.model.cjs +23 -8
  77. package/dist/data/ai/SessionViewer.model.cjs.map +1 -1
  78. package/dist/data/ai/SessionViewer.model.d.ts +8 -0
  79. package/dist/data/ai/SessionViewer.model.d.ts.map +1 -1
  80. package/dist/data/ai/SessionViewer.model.js +23 -8
  81. package/dist/data/ai/SessionViewer.model.js.map +1 -1
  82. package/dist/data/ai/SessionViewer.rows.cjs +9 -1
  83. package/dist/data/ai/SessionViewer.rows.cjs.map +1 -1
  84. package/dist/data/ai/SessionViewer.rows.js +9 -1
  85. package/dist/data/ai/SessionViewer.rows.js.map +1 -1
  86. package/dist/data/ai/SpecRuntimeEditor/VerifySection.cjs +24 -2
  87. package/dist/data/ai/SpecRuntimeEditor/VerifySection.cjs.map +1 -1
  88. package/dist/data/ai/SpecRuntimeEditor/VerifySection.d.ts.map +1 -1
  89. package/dist/data/ai/SpecRuntimeEditor/VerifySection.js +25 -3
  90. package/dist/data/ai/SpecRuntimeEditor/VerifySection.js.map +1 -1
  91. package/dist/data/ai/SpecRuntimeEditor/summaries.cjs.map +1 -1
  92. package/dist/data/ai/SpecRuntimeEditor/summaries.d.ts.map +1 -1
  93. package/dist/data/ai/SpecRuntimeEditor/summaries.js.map +1 -1
  94. package/dist/data/ai/SpecRuntimeEditor.model.cjs +4 -0
  95. package/dist/data/ai/SpecRuntimeEditor.model.cjs.map +1 -1
  96. package/dist/data/ai/SpecRuntimeEditor.model.d.ts +4 -0
  97. package/dist/data/ai/SpecRuntimeEditor.model.d.ts.map +1 -1
  98. package/dist/data/ai/SpecRuntimeEditor.model.js +4 -0
  99. package/dist/data/ai/SpecRuntimeEditor.model.js.map +1 -1
  100. package/dist/data/test-runner/TestRunner.cjs +6 -4
  101. package/dist/data/test-runner/TestRunner.cjs.map +1 -1
  102. package/dist/data/test-runner/TestRunner.d.ts +10 -1
  103. package/dist/data/test-runner/TestRunner.d.ts.map +1 -1
  104. package/dist/data/test-runner/TestRunner.js +6 -4
  105. package/dist/data/test-runner/TestRunner.js.map +1 -1
  106. package/dist/data/test-runner/status.cjs +1 -1
  107. package/dist/data/test-runner/status.cjs.map +1 -1
  108. package/dist/data/test-runner/status.js +1 -1
  109. package/dist/data/test-runner/status.js.map +1 -1
  110. package/dist/data/test-runner/types.d.ts +6 -0
  111. package/dist/data/test-runner/types.d.ts.map +1 -1
  112. package/dist/data/verification/VerificationResults.cjs +99 -0
  113. package/dist/data/verification/VerificationResults.cjs.map +1 -0
  114. package/dist/data/verification/VerificationResults.d.ts +27 -0
  115. package/dist/data/verification/VerificationResults.d.ts.map +1 -0
  116. package/dist/data/verification/VerificationResults.js +99 -0
  117. package/dist/data/verification/VerificationResults.js.map +1 -0
  118. package/dist/data/verification/adapterViews.cjs +116 -0
  119. package/dist/data/verification/adapterViews.cjs.map +1 -0
  120. package/dist/data/verification/adapterViews.d.ts +13 -0
  121. package/dist/data/verification/adapterViews.d.ts.map +1 -0
  122. package/dist/data/verification/adapterViews.js +116 -0
  123. package/dist/data/verification/adapterViews.js.map +1 -0
  124. package/dist/data/verification/adapters.cjs +26 -0
  125. package/dist/data/verification/adapters.cjs.map +1 -0
  126. package/dist/data/verification/adapters.d.ts +6 -0
  127. package/dist/data/verification/adapters.d.ts.map +1 -0
  128. package/dist/data/verification/adapters.js +26 -0
  129. package/dist/data/verification/adapters.js.map +1 -0
  130. package/dist/data/verification/index.d.ts +5 -0
  131. package/dist/data/verification/index.d.ts.map +1 -0
  132. package/dist/data/verification/verify-report.cjs +58 -0
  133. package/dist/data/verification/verify-report.cjs.map +1 -0
  134. package/dist/data/verification/verify-report.d.ts +96 -0
  135. package/dist/data/verification/verify-report.d.ts.map +1 -0
  136. package/dist/data/verification/verify-report.js +58 -0
  137. package/dist/data/verification/verify-report.js.map +1 -0
  138. package/dist/data/verification/verifyReportTests.cjs +84 -0
  139. package/dist/data/verification/verifyReportTests.cjs.map +1 -0
  140. package/dist/data/verification/verifyReportTests.d.ts +13 -0
  141. package/dist/data/verification/verifyReportTests.d.ts.map +1 -0
  142. package/dist/data/verification/verifyReportTests.js +84 -0
  143. package/dist/data/verification/verifyReportTests.js.map +1 -0
  144. package/dist/data/version-info.cjs +3 -3
  145. package/dist/data/version-info.js +3 -3
  146. package/dist/data.cjs +10 -0
  147. package/dist/data.cjs.map +1 -1
  148. package/dist/data.d.ts +1 -0
  149. package/dist/data.d.ts.map +1 -1
  150. package/dist/data.js +10 -0
  151. package/dist/data.js.map +1 -1
  152. package/dist/index.cjs +13 -0
  153. package/dist/index.cjs.map +1 -1
  154. package/dist/index.js +14 -1
  155. package/dist/index.js.map +1 -1
  156. package/dist/styles.css +1 -1
  157. package/package.json +1 -1
@@ -1 +1 @@
1
- {"version":3,"file":"ComboboxMenu.js","sources":["../../src/components/ComboboxMenu.tsx"],"sourcesContent":["import { Fragment, type ReactNode, type RefObject } from \"react\";\nimport { createPortal } from \"react-dom\";\nimport { FilterPill } from \"../data/FilterPill\";\nimport { Icon, LabelIcon } from \"../data/Icon\";\nimport { UiCheck } from \"../icons\";\nimport { cn } from \"../lib/utils\";\nimport type { ComboboxOption, ComboboxTriStateMode } from \"./combobox-types\";\nimport type { ComboboxMenuPosition } from \"../lib/combobox\";\n\nexport function ComboboxMenu({\n customEntry,\n filtered,\n floatingZ,\n footer,\n hasOptions,\n highlighted,\n isSelected,\n listId,\n listRef,\n loading,\n menuPos,\n modes,\n multiple,\n onHighlight,\n onSelect,\n onSetMode,\n tristate,\n}: {\n customEntry: ComboboxOption | null;\n filtered: ComboboxOption[];\n floatingZ: number;\n footer: ReactNode;\n /** Whether the control has an option set at all (before filtering). */\n hasOptions: boolean;\n highlighted: number;\n isSelected: (value: string) => boolean;\n listId: string | undefined;\n listRef: RefObject<HTMLDivElement | null>;\n loading: boolean | undefined;\n menuPos: ComboboxMenuPosition;\n modes: Record<string, ComboboxTriStateMode>;\n multiple: boolean;\n onHighlight: (index: number) => void;\n onSelect: (option: ComboboxOption) => void;\n onSetMode: (value: string, mode: string) => void;\n tristate: boolean;\n}) {\n const mobile = menuPos.strategy === \"mobile\";\n const listbox = (\n <div\n id={listId}\n ref={listRef}\n role=\"listbox\"\n aria-multiselectable={multiple || undefined}\n style={{\n position: mobile ? \"absolute\" : \"fixed\",\n ...(menuPos.top != null\n ? { top: menuPos.top }\n : { bottom: menuPos.bottom }),\n left: menuPos.left,\n ...(mobile ? { width: menuPos.width } : { minWidth: menuPos.width }),\n maxWidth: menuPos.maxWidth,\n maxHeight: menuPos.maxHeight,\n zIndex: mobile ? undefined : floatingZ,\n pointerEvents: mobile ? \"auto\" : undefined,\n }}\n className={cn(\n \"overflow-auto rounded-md border border-border bg-popover p-1 text-popover-foreground shadow-lg shadow-black/5\",\n !mobile && \"w-max\",\n )}\n >\n {loading && filtered.length === 0 && (\n <div className=\"px-2 py-4 text-center text-sm text-muted-foreground\">\n Loading…\n </div>\n )}\n {/* \"No results\" answers \"did my query match anything?\" — a control with\n no option set at all (a free tag list) was never asked the question, so\n it says nothing rather than reporting an empty search. */}\n {!loading && filtered.length === 0 && !customEntry && hasOptions && (\n <div className=\"px-2 py-4 text-center text-sm text-muted-foreground\">\n No results\n </div>\n )}\n {filtered.map((option, index) => {\n const selected = isSelected(option.value);\n const mode = tristate ? modes[option.value] : undefined;\n const showHeader =\n option.group != null && option.group !== filtered[index - 1]?.group;\n return (\n <Fragment key={option.value}>\n {showHeader && (\n <div\n role=\"presentation\"\n className=\"select-none px-2 pb-1 pt-2 text-[10px] font-medium uppercase tracking-wide text-muted-foreground\"\n >\n {option.group}\n </div>\n )}\n <div\n id={listId ? `${listId}-${index}` : undefined}\n role=\"option\"\n aria-selected={tristate ? mode != null : selected}\n aria-disabled={option.disabled}\n {...(mode != null\n ? {\n \"aria-label\": `${option.label}, ${\n mode === \"include\" ? \"included\" : \"excluded\"\n }`,\n }\n : {})}\n {...(option.title !== undefined ? { title: option.title } : {})}\n {...(tristate ? { \"data-filter-option\": option.value } : {})}\n onMouseDown={(event) => {\n event.preventDefault();\n if (!tristate && !option.disabled) onSelect(option);\n }}\n {...(tristate\n ? {\n onClick: () => {\n if (!option.disabled) onSelect(option);\n },\n }\n : {})}\n onMouseEnter={() => onHighlight(index)}\n className={cn(\n \"flex cursor-pointer gap-2 rounded-sm px-2 py-1.5 text-sm\",\n option.description ? \"items-start\" : \"items-center\",\n index === highlighted && \"bg-accent\",\n selected && !tristate && \"font-medium\",\n option.disabled && \"cursor-not-allowed opacity-50\",\n )}\n >\n {tristate ? (\n <div className=\"min-w-0 flex-1\">\n <FilterPill\n mode={mode ?? \"neutral\"}\n togglePosition=\"right\"\n interactive={false}\n label={option.label}\n onModeChange={(next) => onSetMode(option.value, next)}\n className=\"w-full justify-between\"\n />\n <ComboboxOptionDescription description={option.description} />\n </div>\n ) : (\n <>\n <Icon\n icon={UiCheck}\n className={cn(\n \"shrink-0 text-xs\",\n option.description && \"mt-1\",\n selected ? \"opacity-100\" : \"opacity-0\",\n )}\n />\n <LabelIcon\n icon={option.icon}\n className={cn(\n \"text-sm text-muted-foreground\",\n option.description && \"mt-1\",\n )}\n />\n <ComboboxOptionText option={option} />\n {option.trailing != null && (\n // Capped and truncating rather than `shrink-0`: in a menu\n // clamped by the viewport edge the label is what identifies\n // the option, so the preview yields first.\n <span className=\"ml-auto min-w-0 max-w-[55%] truncate pl-2 text-right text-xs text-muted-foreground\">\n {option.trailing}\n </span>\n )}\n </>\n )}\n </div>\n </Fragment>\n );\n })}\n {customEntry && (\n <div\n id={listId ? `${listId}-${filtered.length}` : undefined}\n role=\"option\"\n aria-selected={false}\n data-filter-add-custom={customEntry.value}\n title={customEntry.title}\n onMouseDown={(event) => event.preventDefault()}\n onClick={() => onSelect(customEntry)}\n onMouseEnter={() => onHighlight(filtered.length)}\n className={cn(\n \"flex cursor-pointer items-center gap-2 rounded-sm px-2 py-1.5 text-sm text-primary\",\n highlighted === filtered.length && \"bg-accent\",\n )}\n >\n <LabelIcon\n icon={customEntry.icon}\n className=\"text-sm text-muted-foreground\"\n />\n <span className=\"min-w-0 truncate\">{customEntry.label}</span>\n </div>\n )}\n {footer != null && (\n <div className=\"select-none px-2 py-1.5 text-[11px] text-muted-foreground\">\n {footer}\n </div>\n )}\n </div>\n );\n return createPortal(\n mobile ? (\n <div\n data-slot=\"combobox-viewport-layer\"\n style={{\n position: \"fixed\",\n inset: 0,\n zIndex: floatingZ,\n pointerEvents: \"none\",\n }}\n >\n {listbox}\n </div>\n ) : (\n listbox\n ),\n document.body,\n );\n}\n\nfunction ComboboxOptionText({ option }: { option: ComboboxOption }) {\n return (\n <span className=\"min-w-0 flex-1\">\n <span className=\"block truncate\">{option.label}</span>\n <ComboboxOptionDescription description={option.description} />\n </span>\n );\n}\n\nfunction ComboboxOptionDescription({\n description,\n}: {\n description: string | undefined;\n}) {\n return description ? (\n <span className=\"mt-0.5 block whitespace-pre-line text-xs font-normal leading-4 text-muted-foreground\">\n {description}\n </span>\n ) : null;\n}\n"],"names":["Fragment"],"mappings":"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"}
1
+ {"version":3,"file":"ComboboxMenu.js","sources":["../../src/components/ComboboxMenu.tsx"],"sourcesContent":["import { Fragment, type ReactNode, type RefObject } from \"react\";\nimport { createPortal } from \"react-dom\";\nimport { FilterPill } from \"../data/FilterPill\";\nimport { Icon, LabelIcon } from \"../data/Icon\";\nimport { UiCheck } from \"../icons\";\nimport { cn } from \"../lib/utils\";\nimport type { ComboboxOption, ComboboxTriStateMode } from \"./combobox-types\";\nimport type { ComboboxMenuPosition } from \"../lib/combobox\";\n\nexport function ComboboxMenu({\n customEntry,\n filtered,\n floatingZ,\n footer,\n hasOptions,\n highlighted,\n isSelected,\n listId,\n listRef,\n loading,\n menuPos,\n modes,\n multiple,\n onHighlight,\n onSelect,\n onSetMode,\n tristate,\n}: {\n customEntry: ComboboxOption | null;\n filtered: ComboboxOption[];\n floatingZ: number;\n footer: ReactNode;\n /** Whether the control has an option set at all (before filtering). */\n hasOptions: boolean;\n highlighted: number;\n isSelected: (value: string) => boolean;\n listId: string | undefined;\n listRef: RefObject<HTMLDivElement | null>;\n loading: boolean | undefined;\n menuPos: ComboboxMenuPosition;\n modes: Record<string, ComboboxTriStateMode>;\n multiple: boolean;\n onHighlight: (index: number) => void;\n onSelect: (option: ComboboxOption) => void;\n onSetMode: (value: string, mode: string) => void;\n tristate: boolean;\n}) {\n const mobile = menuPos.strategy === \"mobile\";\n const listbox = (\n <div\n id={listId}\n ref={listRef}\n role=\"listbox\"\n aria-multiselectable={multiple || undefined}\n style={{\n position: mobile ? \"absolute\" : \"fixed\",\n ...(menuPos.top != null\n ? { top: menuPos.top }\n : { bottom: menuPos.bottom }),\n left: menuPos.left,\n ...(mobile ? { width: menuPos.width } : { minWidth: menuPos.width }),\n maxWidth: menuPos.maxWidth,\n maxHeight: menuPos.maxHeight,\n zIndex: mobile ? undefined : floatingZ,\n pointerEvents: mobile ? \"auto\" : undefined,\n }}\n className={cn(\n \"overflow-auto rounded-md border border-border bg-popover p-1 text-popover-foreground shadow-lg shadow-black/5\",\n !mobile && \"w-max\",\n )}\n >\n {loading && filtered.length === 0 && (\n <div className=\"px-2 py-4 text-center text-sm text-muted-foreground\">\n Loading…\n </div>\n )}\n {/* \"No results\" answers \"did my query match anything?\" — a control with\n no option set at all (a free tag list) was never asked the question, so\n it says nothing rather than reporting an empty search. */}\n {!loading && filtered.length === 0 && !customEntry && hasOptions && (\n <div className=\"px-2 py-4 text-center text-sm text-muted-foreground\">\n No results\n </div>\n )}\n {filtered.map((option, index) => {\n const selected = isSelected(option.value);\n const mode = tristate ? modes[option.value] : undefined;\n const showHeader =\n option.group != null && option.group !== filtered[index - 1]?.group;\n return (\n <Fragment key={option.value}>\n {showHeader && (\n <div\n role=\"presentation\"\n className=\"select-none px-2 pb-1 pt-2 text-[10px] font-medium uppercase tracking-wide text-muted-foreground\"\n >\n {option.group}\n </div>\n )}\n <div\n id={listId ? `${listId}-${index}` : undefined}\n role=\"option\"\n aria-selected={tristate ? mode != null : selected}\n aria-disabled={option.disabled}\n {...(mode != null\n ? {\n \"aria-label\": `${option.label}, ${\n mode === \"include\" ? \"included\" : \"excluded\"\n }`,\n }\n : {})}\n {...(option.title !== undefined ? { title: option.title } : {})}\n {...(tristate ? { \"data-filter-option\": option.value } : {})}\n onMouseDown={(event) => {\n event.preventDefault();\n if (!tristate && !option.disabled) onSelect(option);\n }}\n {...(tristate\n ? {\n onClick: () => {\n if (!option.disabled) onSelect(option);\n },\n }\n : {})}\n onMouseEnter={() => onHighlight(index)}\n className={cn(\n \"flex cursor-pointer gap-2 rounded-sm px-2 py-1.5 text-sm\",\n option.description ? \"items-start\" : \"items-center\",\n index === highlighted && \"bg-accent\",\n selected && !tristate && \"font-medium\",\n option.disabled && \"cursor-not-allowed opacity-50\",\n )}\n >\n {tristate ? (\n <div className=\"min-w-0 flex-1\">\n <FilterPill\n mode={mode ?? \"neutral\"}\n togglePosition=\"right\"\n interactive={false}\n label={\n <span className=\"inline-flex min-w-0 items-center gap-1.5\">\n <LabelIcon icon={option.icon} className=\"shrink-0 text-sm text-muted-foreground\" />\n <span className=\"truncate\">{option.label}</span>\n </span>\n }\n onModeChange={(next) => onSetMode(option.value, next)}\n className=\"w-full justify-between\"\n />\n <ComboboxOptionDescription description={option.description} />\n </div>\n ) : (\n <>\n <Icon\n icon={UiCheck}\n className={cn(\n \"shrink-0 text-xs\",\n option.description && \"mt-1\",\n selected ? \"opacity-100\" : \"opacity-0\",\n )}\n />\n <LabelIcon\n icon={option.icon}\n className={cn(\n \"text-sm text-muted-foreground\",\n option.description && \"mt-1\",\n )}\n />\n <ComboboxOptionText option={option} />\n {option.trailing != null && (\n // Capped and truncating rather than `shrink-0`: in a menu\n // clamped by the viewport edge the label is what identifies\n // the option, so the preview yields first.\n <span className=\"ml-auto min-w-0 max-w-[55%] truncate pl-2 text-right text-xs text-muted-foreground\">\n {option.trailing}\n </span>\n )}\n </>\n )}\n </div>\n </Fragment>\n );\n })}\n {customEntry && (\n <div\n id={listId ? `${listId}-${filtered.length}` : undefined}\n role=\"option\"\n aria-selected={false}\n data-filter-add-custom={customEntry.value}\n title={customEntry.title}\n onMouseDown={(event) => event.preventDefault()}\n onClick={() => onSelect(customEntry)}\n onMouseEnter={() => onHighlight(filtered.length)}\n className={cn(\n \"flex cursor-pointer items-center gap-2 rounded-sm px-2 py-1.5 text-sm text-primary\",\n highlighted === filtered.length && \"bg-accent\",\n )}\n >\n <LabelIcon\n icon={customEntry.icon}\n className=\"text-sm text-muted-foreground\"\n />\n <span className=\"min-w-0 truncate\">{customEntry.label}</span>\n </div>\n )}\n {footer != null && (\n <div className=\"select-none px-2 py-1.5 text-[11px] text-muted-foreground\">\n {footer}\n </div>\n )}\n </div>\n );\n return createPortal(\n mobile ? (\n <div\n data-slot=\"combobox-viewport-layer\"\n style={{\n position: \"fixed\",\n inset: 0,\n zIndex: floatingZ,\n pointerEvents: \"none\",\n }}\n >\n {listbox}\n </div>\n ) : (\n listbox\n ),\n document.body,\n );\n}\n\nfunction ComboboxOptionText({ option }: { option: ComboboxOption }) {\n return (\n <span className=\"min-w-0 flex-1\">\n <span className=\"block truncate\">{option.label}</span>\n <ComboboxOptionDescription description={option.description} />\n </span>\n );\n}\n\nfunction ComboboxOptionDescription({\n description,\n}: {\n description: string | undefined;\n}) {\n return description ? (\n <span className=\"mt-0.5 block whitespace-pre-line text-xs font-normal leading-4 text-muted-foreground\">\n {description}\n </span>\n ) : null;\n}\n"],"names":["Fragment"],"mappings":"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"}
@@ -39,7 +39,10 @@ function ComboboxTags({
39
39
  FilterPill.FilterPill,
40
40
  {
41
41
  mode,
42
- label,
42
+ label: /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "inline-flex min-w-0 items-center gap-1.5", children: [
43
+ /* @__PURE__ */ jsxRuntime.jsx(Icon.LabelIcon, { icon: option == null ? void 0 : option.icon, className: "shrink-0 text-muted-foreground" }),
44
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "truncate", children: label })
45
+ ] }),
43
46
  title: mode === "include" ? `${label} included` : `${label} excluded`,
44
47
  className: "max-w-full",
45
48
  ...disabled ? {} : {
@@ -59,6 +62,7 @@ function ComboboxTags({
59
62
  "data-combobox-tag": value,
60
63
  className: "inline-flex h-6 max-w-full items-center gap-1 rounded-md bg-muted px-2 text-xs",
61
64
  children: [
65
+ /* @__PURE__ */ jsxRuntime.jsx(Icon.LabelIcon, { icon: option == null ? void 0 : option.icon, className: "shrink-0 text-muted-foreground" }),
62
66
  /* @__PURE__ */ jsxRuntime.jsx("span", { className: "truncate", children: label }),
63
67
  remove
64
68
  ]
@@ -1 +1 @@
1
- {"version":3,"file":"ComboboxTags.cjs","sources":["../../src/components/ComboboxTags.tsx"],"sourcesContent":["import { Icon } from \"../data/Icon\";\nimport { FilterPill } from \"../data/FilterPill\";\nimport { UiClose } from \"../icons\";\nimport type { ComboboxOption, ComboboxTriStateMode } from \"./combobox-types\";\n\nexport function ComboboxTags({\n disabled,\n modes,\n onRemove,\n onSetMode,\n options,\n values,\n}: {\n disabled: boolean | undefined;\n /** Per-value include/exclude modes; set only in tristate mode. */\n modes: Record<string, ComboboxTriStateMode> | undefined;\n onRemove: (value: string) => void;\n onSetMode: (value: string, mode: string) => void;\n options: ComboboxOption[];\n values: string[];\n}) {\n return values.map((value, index) => {\n const option = options.find((entry) => entry.value === value);\n const label = option?.selectedLabel ?? option?.label ?? value;\n const mode = modes?.[value];\n const remove = !disabled && (\n <button\n type=\"button\"\n aria-label={`Remove ${label}`}\n className=\"shrink-0 text-muted-foreground hover:text-foreground\"\n onMouseDown={(event) => event.preventDefault()}\n onClick={() => onRemove(value)}\n >\n <Icon icon={UiClose} className=\"size-3\" />\n </button>\n );\n\n // A tristate pill carries its mode in the same colours the menu rows use.\n // The pill body flips include ↔ exclude; returning to neutral is what the\n // close button means, so the two affordances never overlap.\n if (mode) {\n return (\n <span\n key={`${value}-${index}`}\n data-combobox-tag={value}\n data-combobox-tag-mode={mode}\n className=\"inline-flex h-6 max-w-full items-center gap-1\"\n >\n <FilterPill\n mode={mode}\n label={label}\n title={mode === \"include\" ? `${label} included` : `${label} excluded`}\n className=\"max-w-full\"\n {...(disabled\n ? {}\n : {\n onClick: () =>\n onSetMode(value, mode === \"include\" ? \"exclude\" : \"include\"),\n })}\n />\n {remove}\n </span>\n );\n }\n\n return (\n <span\n key={`${value}-${index}`}\n data-combobox-tag={value}\n className=\"inline-flex h-6 max-w-full items-center gap-1 rounded-md bg-muted px-2 text-xs\"\n >\n <span className=\"truncate\">{label}</span>\n {remove}\n </span>\n );\n });\n}\n"],"names":["jsx","Icon","UiClose","jsxs","FilterPill"],"mappings":";;;;;;AAKO,SAAS,aAAa;AAAA,EAC3B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAQG;AACD,SAAO,OAAO,IAAI,CAAC,OAAO,UAAU;AAClC,UAAM,SAAS,QAAQ,KAAK,CAAC,UAAU,MAAM,UAAU,KAAK;AAC5D,UAAM,SAAQ,iCAAQ,mBAAiB,iCAAQ,UAAS;AACxD,UAAM,OAAO,+BAAQ;AACrB,UAAM,SAAS,CAAC,YACdA,2BAAAA;AAAAA,MAAC;AAAA,MAAA;AAAA,QACC,MAAK;AAAA,QACL,cAAY,UAAU,KAAK;AAAA,QAC3B,WAAU;AAAA,QACV,aAAa,CAAC,UAAU,MAAM,eAAA;AAAA,QAC9B,SAAS,MAAM,SAAS,KAAK;AAAA,QAE7B,UAAAA,2BAAAA,IAACC,WAAA,EAAK,MAAMC,QAAAA,SAAS,WAAU,SAAA,CAAS;AAAA,MAAA;AAAA,IAAA;AAO5C,QAAI,MAAM;AACR,aACEC,2BAAAA;AAAAA,QAAC;AAAA,QAAA;AAAA,UAEC,qBAAmB;AAAA,UACnB,0BAAwB;AAAA,UACxB,WAAU;AAAA,UAEV,UAAA;AAAA,YAAAH,2BAAAA;AAAAA,cAACI,WAAAA;AAAAA,cAAA;AAAA,gBACC;AAAA,gBACA;AAAA,gBACA,OAAO,SAAS,YAAY,GAAG,KAAK,cAAc,GAAG,KAAK;AAAA,gBAC1D,WAAU;AAAA,gBACT,GAAI,WACD,CAAA,IACA;AAAA,kBACE,SAAS,MACP,UAAU,OAAO,SAAS,YAAY,YAAY,SAAS;AAAA,gBAAA;AAAA,cAC/D;AAAA,YAAA;AAAA,YAEL;AAAA,UAAA;AAAA,QAAA;AAAA,QAjBI,GAAG,KAAK,IAAI,KAAK;AAAA,MAAA;AAAA,IAoB5B;AAEA,WACED,2BAAAA;AAAAA,MAAC;AAAA,MAAA;AAAA,QAEC,qBAAmB;AAAA,QACnB,WAAU;AAAA,QAEV,UAAA;AAAA,UAAAH,2BAAAA,IAAC,QAAA,EAAK,WAAU,YAAY,UAAA,OAAM;AAAA,UACjC;AAAA,QAAA;AAAA,MAAA;AAAA,MALI,GAAG,KAAK,IAAI,KAAK;AAAA,IAAA;AAAA,EAQ5B,CAAC;AACH;;"}
1
+ {"version":3,"file":"ComboboxTags.cjs","sources":["../../src/components/ComboboxTags.tsx"],"sourcesContent":["import { Icon, LabelIcon } from \"../data/Icon\";\nimport { FilterPill } from \"../data/FilterPill\";\nimport { UiClose } from \"../icons\";\nimport type { ComboboxOption, ComboboxTriStateMode } from \"./combobox-types\";\n\nexport function ComboboxTags({\n disabled,\n modes,\n onRemove,\n onSetMode,\n options,\n values,\n}: {\n disabled: boolean | undefined;\n /** Per-value include/exclude modes; set only in tristate mode. */\n modes: Record<string, ComboboxTriStateMode> | undefined;\n onRemove: (value: string) => void;\n onSetMode: (value: string, mode: string) => void;\n options: ComboboxOption[];\n values: string[];\n}) {\n return values.map((value, index) => {\n const option = options.find((entry) => entry.value === value);\n const label = option?.selectedLabel ?? option?.label ?? value;\n const mode = modes?.[value];\n const remove = !disabled && (\n <button\n type=\"button\"\n aria-label={`Remove ${label}`}\n className=\"shrink-0 text-muted-foreground hover:text-foreground\"\n onMouseDown={(event) => event.preventDefault()}\n onClick={() => onRemove(value)}\n >\n <Icon icon={UiClose} className=\"size-3\" />\n </button>\n );\n\n // A tristate pill carries its mode in the same colours the menu rows use.\n // The pill body flips include ↔ exclude; returning to neutral is what the\n // close button means, so the two affordances never overlap.\n if (mode) {\n return (\n <span\n key={`${value}-${index}`}\n data-combobox-tag={value}\n data-combobox-tag-mode={mode}\n className=\"inline-flex h-6 max-w-full items-center gap-1\"\n >\n <FilterPill\n mode={mode}\n label={\n <span className=\"inline-flex min-w-0 items-center gap-1.5\">\n <LabelIcon icon={option?.icon} className=\"shrink-0 text-muted-foreground\" />\n <span className=\"truncate\">{label}</span>\n </span>\n }\n title={mode === \"include\" ? `${label} included` : `${label} excluded`}\n className=\"max-w-full\"\n {...(disabled\n ? {}\n : {\n onClick: () =>\n onSetMode(value, mode === \"include\" ? \"exclude\" : \"include\"),\n })}\n />\n {remove}\n </span>\n );\n }\n\n return (\n <span\n key={`${value}-${index}`}\n data-combobox-tag={value}\n className=\"inline-flex h-6 max-w-full items-center gap-1 rounded-md bg-muted px-2 text-xs\"\n >\n <LabelIcon icon={option?.icon} className=\"shrink-0 text-muted-foreground\" />\n <span className=\"truncate\">{label}</span>\n {remove}\n </span>\n );\n });\n}\n"],"names":["jsx","Icon","UiClose","jsxs","FilterPill","LabelIcon"],"mappings":";;;;;;AAKO,SAAS,aAAa;AAAA,EAC3B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAQG;AACD,SAAO,OAAO,IAAI,CAAC,OAAO,UAAU;AAClC,UAAM,SAAS,QAAQ,KAAK,CAAC,UAAU,MAAM,UAAU,KAAK;AAC5D,UAAM,SAAQ,iCAAQ,mBAAiB,iCAAQ,UAAS;AACxD,UAAM,OAAO,+BAAQ;AACrB,UAAM,SAAS,CAAC,YACdA,2BAAAA;AAAAA,MAAC;AAAA,MAAA;AAAA,QACC,MAAK;AAAA,QACL,cAAY,UAAU,KAAK;AAAA,QAC3B,WAAU;AAAA,QACV,aAAa,CAAC,UAAU,MAAM,eAAA;AAAA,QAC9B,SAAS,MAAM,SAAS,KAAK;AAAA,QAE7B,UAAAA,2BAAAA,IAACC,WAAA,EAAK,MAAMC,QAAAA,SAAS,WAAU,SAAA,CAAS;AAAA,MAAA;AAAA,IAAA;AAO5C,QAAI,MAAM;AACR,aACEC,2BAAAA;AAAAA,QAAC;AAAA,QAAA;AAAA,UAEC,qBAAmB;AAAA,UACnB,0BAAwB;AAAA,UACxB,WAAU;AAAA,UAEV,UAAA;AAAA,YAAAH,2BAAAA;AAAAA,cAACI,WAAAA;AAAAA,cAAA;AAAA,gBACC;AAAA,gBACA,OACED,2BAAAA,KAAC,QAAA,EAAK,WAAU,4CACd,UAAA;AAAA,kBAAAH,2BAAAA,IAACK,KAAAA,WAAA,EAAU,MAAM,iCAAQ,MAAM,WAAU,kCAAiC;AAAA,kBAC1EL,2BAAAA,IAAC,QAAA,EAAK,WAAU,YAAY,UAAA,MAAA,CAAM;AAAA,gBAAA,GACpC;AAAA,gBAEF,OAAO,SAAS,YAAY,GAAG,KAAK,cAAc,GAAG,KAAK;AAAA,gBAC1D,WAAU;AAAA,gBACT,GAAI,WACD,CAAA,IACA;AAAA,kBACE,SAAS,MACP,UAAU,OAAO,SAAS,YAAY,YAAY,SAAS;AAAA,gBAAA;AAAA,cAC/D;AAAA,YAAA;AAAA,YAEL;AAAA,UAAA;AAAA,QAAA;AAAA,QAtBI,GAAG,KAAK,IAAI,KAAK;AAAA,MAAA;AAAA,IAyB5B;AAEA,WACEG,2BAAAA;AAAAA,MAAC;AAAA,MAAA;AAAA,QAEC,qBAAmB;AAAA,QACnB,WAAU;AAAA,QAEV,UAAA;AAAA,UAAAH,2BAAAA,IAACK,KAAAA,WAAA,EAAU,MAAM,iCAAQ,MAAM,WAAU,kCAAiC;AAAA,UAC1EL,2BAAAA,IAAC,QAAA,EAAK,WAAU,YAAY,UAAA,OAAM;AAAA,UACjC;AAAA,QAAA;AAAA,MAAA;AAAA,MANI,GAAG,KAAK,IAAI,KAAK;AAAA,IAAA;AAAA,EAS5B,CAAC;AACH;;"}
@@ -1 +1 @@
1
- {"version":3,"file":"ComboboxTags.d.ts","sourceRoot":"","sources":["../../src/components/ComboboxTags.tsx"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,cAAc,EAAE,oBAAoB,EAAE,MAAM,kBAAkB,CAAC;AAE7E,wBAAgB,YAAY,CAAC,EAC3B,QAAQ,EACR,KAAK,EACL,QAAQ,EACR,SAAS,EACT,OAAO,EACP,MAAM,GACP,EAAE;IACD,QAAQ,EAAE,OAAO,GAAG,SAAS,CAAC;IAC9B,kEAAkE;IAClE,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,oBAAoB,CAAC,GAAG,SAAS,CAAC;IACxD,QAAQ,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IAClC,SAAS,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IACjD,OAAO,EAAE,cAAc,EAAE,CAAC;IAC1B,MAAM,EAAE,MAAM,EAAE,CAAC;CAClB,iCAwDA"}
1
+ {"version":3,"file":"ComboboxTags.d.ts","sourceRoot":"","sources":["../../src/components/ComboboxTags.tsx"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,cAAc,EAAE,oBAAoB,EAAE,MAAM,kBAAkB,CAAC;AAE7E,wBAAgB,YAAY,CAAC,EAC3B,QAAQ,EACR,KAAK,EACL,QAAQ,EACR,SAAS,EACT,OAAO,EACP,MAAM,GACP,EAAE;IACD,QAAQ,EAAE,OAAO,GAAG,SAAS,CAAC;IAC9B,kEAAkE;IAClE,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,oBAAoB,CAAC,GAAG,SAAS,CAAC;IACxD,QAAQ,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IAClC,SAAS,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IACjD,OAAO,EAAE,cAAc,EAAE,CAAC;IAC1B,MAAM,EAAE,MAAM,EAAE,CAAC;CAClB,iCA8DA"}
@@ -1,5 +1,5 @@
1
1
  import { jsxs, jsx } from "react/jsx-runtime";
2
- import { Icon } from "../data/Icon.js";
2
+ import { LabelIcon, Icon } from "../data/Icon.js";
3
3
  import { FilterPill } from "../data/FilterPill.js";
4
4
  import { UiClose } from "../icons/components/UiClose.js";
5
5
  function ComboboxTags({
@@ -37,7 +37,10 @@ function ComboboxTags({
37
37
  FilterPill,
38
38
  {
39
39
  mode,
40
- label,
40
+ label: /* @__PURE__ */ jsxs("span", { className: "inline-flex min-w-0 items-center gap-1.5", children: [
41
+ /* @__PURE__ */ jsx(LabelIcon, { icon: option == null ? void 0 : option.icon, className: "shrink-0 text-muted-foreground" }),
42
+ /* @__PURE__ */ jsx("span", { className: "truncate", children: label })
43
+ ] }),
41
44
  title: mode === "include" ? `${label} included` : `${label} excluded`,
42
45
  className: "max-w-full",
43
46
  ...disabled ? {} : {
@@ -57,6 +60,7 @@ function ComboboxTags({
57
60
  "data-combobox-tag": value,
58
61
  className: "inline-flex h-6 max-w-full items-center gap-1 rounded-md bg-muted px-2 text-xs",
59
62
  children: [
63
+ /* @__PURE__ */ jsx(LabelIcon, { icon: option == null ? void 0 : option.icon, className: "shrink-0 text-muted-foreground" }),
60
64
  /* @__PURE__ */ jsx("span", { className: "truncate", children: label }),
61
65
  remove
62
66
  ]
@@ -1 +1 @@
1
- {"version":3,"file":"ComboboxTags.js","sources":["../../src/components/ComboboxTags.tsx"],"sourcesContent":["import { Icon } from \"../data/Icon\";\nimport { FilterPill } from \"../data/FilterPill\";\nimport { UiClose } from \"../icons\";\nimport type { ComboboxOption, ComboboxTriStateMode } from \"./combobox-types\";\n\nexport function ComboboxTags({\n disabled,\n modes,\n onRemove,\n onSetMode,\n options,\n values,\n}: {\n disabled: boolean | undefined;\n /** Per-value include/exclude modes; set only in tristate mode. */\n modes: Record<string, ComboboxTriStateMode> | undefined;\n onRemove: (value: string) => void;\n onSetMode: (value: string, mode: string) => void;\n options: ComboboxOption[];\n values: string[];\n}) {\n return values.map((value, index) => {\n const option = options.find((entry) => entry.value === value);\n const label = option?.selectedLabel ?? option?.label ?? value;\n const mode = modes?.[value];\n const remove = !disabled && (\n <button\n type=\"button\"\n aria-label={`Remove ${label}`}\n className=\"shrink-0 text-muted-foreground hover:text-foreground\"\n onMouseDown={(event) => event.preventDefault()}\n onClick={() => onRemove(value)}\n >\n <Icon icon={UiClose} className=\"size-3\" />\n </button>\n );\n\n // A tristate pill carries its mode in the same colours the menu rows use.\n // The pill body flips include ↔ exclude; returning to neutral is what the\n // close button means, so the two affordances never overlap.\n if (mode) {\n return (\n <span\n key={`${value}-${index}`}\n data-combobox-tag={value}\n data-combobox-tag-mode={mode}\n className=\"inline-flex h-6 max-w-full items-center gap-1\"\n >\n <FilterPill\n mode={mode}\n label={label}\n title={mode === \"include\" ? `${label} included` : `${label} excluded`}\n className=\"max-w-full\"\n {...(disabled\n ? {}\n : {\n onClick: () =>\n onSetMode(value, mode === \"include\" ? \"exclude\" : \"include\"),\n })}\n />\n {remove}\n </span>\n );\n }\n\n return (\n <span\n key={`${value}-${index}`}\n data-combobox-tag={value}\n className=\"inline-flex h-6 max-w-full items-center gap-1 rounded-md bg-muted px-2 text-xs\"\n >\n <span className=\"truncate\">{label}</span>\n {remove}\n </span>\n );\n });\n}\n"],"names":[],"mappings":";;;;AAKO,SAAS,aAAa;AAAA,EAC3B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAQG;AACD,SAAO,OAAO,IAAI,CAAC,OAAO,UAAU;AAClC,UAAM,SAAS,QAAQ,KAAK,CAAC,UAAU,MAAM,UAAU,KAAK;AAC5D,UAAM,SAAQ,iCAAQ,mBAAiB,iCAAQ,UAAS;AACxD,UAAM,OAAO,+BAAQ;AACrB,UAAM,SAAS,CAAC,YACd;AAAA,MAAC;AAAA,MAAA;AAAA,QACC,MAAK;AAAA,QACL,cAAY,UAAU,KAAK;AAAA,QAC3B,WAAU;AAAA,QACV,aAAa,CAAC,UAAU,MAAM,eAAA;AAAA,QAC9B,SAAS,MAAM,SAAS,KAAK;AAAA,QAE7B,UAAA,oBAAC,MAAA,EAAK,MAAM,SAAS,WAAU,SAAA,CAAS;AAAA,MAAA;AAAA,IAAA;AAO5C,QAAI,MAAM;AACR,aACE;AAAA,QAAC;AAAA,QAAA;AAAA,UAEC,qBAAmB;AAAA,UACnB,0BAAwB;AAAA,UACxB,WAAU;AAAA,UAEV,UAAA;AAAA,YAAA;AAAA,cAAC;AAAA,cAAA;AAAA,gBACC;AAAA,gBACA;AAAA,gBACA,OAAO,SAAS,YAAY,GAAG,KAAK,cAAc,GAAG,KAAK;AAAA,gBAC1D,WAAU;AAAA,gBACT,GAAI,WACD,CAAA,IACA;AAAA,kBACE,SAAS,MACP,UAAU,OAAO,SAAS,YAAY,YAAY,SAAS;AAAA,gBAAA;AAAA,cAC/D;AAAA,YAAA;AAAA,YAEL;AAAA,UAAA;AAAA,QAAA;AAAA,QAjBI,GAAG,KAAK,IAAI,KAAK;AAAA,MAAA;AAAA,IAoB5B;AAEA,WACE;AAAA,MAAC;AAAA,MAAA;AAAA,QAEC,qBAAmB;AAAA,QACnB,WAAU;AAAA,QAEV,UAAA;AAAA,UAAA,oBAAC,QAAA,EAAK,WAAU,YAAY,UAAA,OAAM;AAAA,UACjC;AAAA,QAAA;AAAA,MAAA;AAAA,MALI,GAAG,KAAK,IAAI,KAAK;AAAA,IAAA;AAAA,EAQ5B,CAAC;AACH;"}
1
+ {"version":3,"file":"ComboboxTags.js","sources":["../../src/components/ComboboxTags.tsx"],"sourcesContent":["import { Icon, LabelIcon } from \"../data/Icon\";\nimport { FilterPill } from \"../data/FilterPill\";\nimport { UiClose } from \"../icons\";\nimport type { ComboboxOption, ComboboxTriStateMode } from \"./combobox-types\";\n\nexport function ComboboxTags({\n disabled,\n modes,\n onRemove,\n onSetMode,\n options,\n values,\n}: {\n disabled: boolean | undefined;\n /** Per-value include/exclude modes; set only in tristate mode. */\n modes: Record<string, ComboboxTriStateMode> | undefined;\n onRemove: (value: string) => void;\n onSetMode: (value: string, mode: string) => void;\n options: ComboboxOption[];\n values: string[];\n}) {\n return values.map((value, index) => {\n const option = options.find((entry) => entry.value === value);\n const label = option?.selectedLabel ?? option?.label ?? value;\n const mode = modes?.[value];\n const remove = !disabled && (\n <button\n type=\"button\"\n aria-label={`Remove ${label}`}\n className=\"shrink-0 text-muted-foreground hover:text-foreground\"\n onMouseDown={(event) => event.preventDefault()}\n onClick={() => onRemove(value)}\n >\n <Icon icon={UiClose} className=\"size-3\" />\n </button>\n );\n\n // A tristate pill carries its mode in the same colours the menu rows use.\n // The pill body flips include ↔ exclude; returning to neutral is what the\n // close button means, so the two affordances never overlap.\n if (mode) {\n return (\n <span\n key={`${value}-${index}`}\n data-combobox-tag={value}\n data-combobox-tag-mode={mode}\n className=\"inline-flex h-6 max-w-full items-center gap-1\"\n >\n <FilterPill\n mode={mode}\n label={\n <span className=\"inline-flex min-w-0 items-center gap-1.5\">\n <LabelIcon icon={option?.icon} className=\"shrink-0 text-muted-foreground\" />\n <span className=\"truncate\">{label}</span>\n </span>\n }\n title={mode === \"include\" ? `${label} included` : `${label} excluded`}\n className=\"max-w-full\"\n {...(disabled\n ? {}\n : {\n onClick: () =>\n onSetMode(value, mode === \"include\" ? \"exclude\" : \"include\"),\n })}\n />\n {remove}\n </span>\n );\n }\n\n return (\n <span\n key={`${value}-${index}`}\n data-combobox-tag={value}\n className=\"inline-flex h-6 max-w-full items-center gap-1 rounded-md bg-muted px-2 text-xs\"\n >\n <LabelIcon icon={option?.icon} className=\"shrink-0 text-muted-foreground\" />\n <span className=\"truncate\">{label}</span>\n {remove}\n </span>\n );\n });\n}\n"],"names":[],"mappings":";;;;AAKO,SAAS,aAAa;AAAA,EAC3B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAQG;AACD,SAAO,OAAO,IAAI,CAAC,OAAO,UAAU;AAClC,UAAM,SAAS,QAAQ,KAAK,CAAC,UAAU,MAAM,UAAU,KAAK;AAC5D,UAAM,SAAQ,iCAAQ,mBAAiB,iCAAQ,UAAS;AACxD,UAAM,OAAO,+BAAQ;AACrB,UAAM,SAAS,CAAC,YACd;AAAA,MAAC;AAAA,MAAA;AAAA,QACC,MAAK;AAAA,QACL,cAAY,UAAU,KAAK;AAAA,QAC3B,WAAU;AAAA,QACV,aAAa,CAAC,UAAU,MAAM,eAAA;AAAA,QAC9B,SAAS,MAAM,SAAS,KAAK;AAAA,QAE7B,UAAA,oBAAC,MAAA,EAAK,MAAM,SAAS,WAAU,SAAA,CAAS;AAAA,MAAA;AAAA,IAAA;AAO5C,QAAI,MAAM;AACR,aACE;AAAA,QAAC;AAAA,QAAA;AAAA,UAEC,qBAAmB;AAAA,UACnB,0BAAwB;AAAA,UACxB,WAAU;AAAA,UAEV,UAAA;AAAA,YAAA;AAAA,cAAC;AAAA,cAAA;AAAA,gBACC;AAAA,gBACA,OACE,qBAAC,QAAA,EAAK,WAAU,4CACd,UAAA;AAAA,kBAAA,oBAAC,WAAA,EAAU,MAAM,iCAAQ,MAAM,WAAU,kCAAiC;AAAA,kBAC1E,oBAAC,QAAA,EAAK,WAAU,YAAY,UAAA,MAAA,CAAM;AAAA,gBAAA,GACpC;AAAA,gBAEF,OAAO,SAAS,YAAY,GAAG,KAAK,cAAc,GAAG,KAAK;AAAA,gBAC1D,WAAU;AAAA,gBACT,GAAI,WACD,CAAA,IACA;AAAA,kBACE,SAAS,MACP,UAAU,OAAO,SAAS,YAAY,YAAY,SAAS;AAAA,gBAAA;AAAA,cAC/D;AAAA,YAAA;AAAA,YAEL;AAAA,UAAA;AAAA,QAAA;AAAA,QAtBI,GAAG,KAAK,IAAI,KAAK;AAAA,MAAA;AAAA,IAyB5B;AAEA,WACE;AAAA,MAAC;AAAA,MAAA;AAAA,QAEC,qBAAmB;AAAA,QACnB,WAAU;AAAA,QAEV,UAAA;AAAA,UAAA,oBAAC,WAAA,EAAU,MAAM,iCAAQ,MAAM,WAAU,kCAAiC;AAAA,UAC1E,oBAAC,QAAA,EAAK,WAAU,YAAY,UAAA,OAAM;AAAA,UACjC;AAAA,QAAA;AAAA,MAAA;AAAA,MANI,GAAG,KAAK,IAAI,KAAK;AAAA,IAAA;AAAA,EAS5B,CAAC;AACH;"}
@@ -13,6 +13,10 @@ const LEVEL_OPTIONS = ConnectionLoggingPolicy_model.CONNECTION_LOG_LEVELS.map((l
13
13
  label: level === "off" ? "Off" : ((_a = level[0]) == null ? void 0 : _a.toUpperCase()) + level.slice(1)
14
14
  };
15
15
  });
16
+ const LEVEL_SEGMENTS = LEVEL_OPTIONS.map(({ value, label }) => ({
17
+ id: value,
18
+ label
19
+ }));
16
20
  const THRESHOLD_PROPERTY = "log.slowThreshold";
17
21
  function ConnectionLoggingPolicy({
18
22
  definition,
@@ -50,7 +54,7 @@ function ConnectionLoggingPolicy({
50
54
  /* @__PURE__ */ jsxRuntime.jsx("h3", { className: "text-sm font-semibold text-foreground", children: "Connection logging" }),
51
55
  /* @__PURE__ */ jsxRuntime.jsx("p", { className: "max-w-3xl text-xs leading-relaxed text-muted-foreground", children: "Errors win over slow operations, then the provider-specific record. Payloads are bounded and credentials are sanitized before logging." })
52
56
  ] }),
53
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "rounded-full border border-border bg-muted px-2 py-1 text-[11px] font-medium uppercase tracking-wide text-muted-foreground", children: definition.family })
57
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-mono text-[11px] font-medium uppercase tracking-wide text-muted-foreground", children: definition.family })
54
58
  ] }),
55
59
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid gap-density-4 xl:grid-cols-[minmax(0,1.2fr)_minmax(22rem,0.8fr)]", children: [
56
60
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-density-3", children: [
@@ -72,51 +76,36 @@ function ConnectionLoggingPolicy({
72
76
  return /* @__PURE__ */ jsxRuntime.jsxs(
73
77
  "div",
74
78
  {
75
- className: "grid gap-density-3 border-b border-border p-density-3 last:border-b-0 md:grid-cols-[minmax(0,1fr)_8rem]",
79
+ className: "grid gap-density-2 border-b border-border px-density-3 py-density-2 last:border-b-0 xl:grid-cols-[minmax(12rem,1fr)_auto] xl:items-center",
76
80
  children: [
77
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "min-w-0 space-y-1.5", children: [
81
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "min-w-0 space-y-1", children: [
78
82
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-wrap items-center gap-2", children: [
79
83
  /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm font-medium text-foreground", children: event.label }),
80
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "rounded bg-muted px-1.5 py-0.5 font-mono text-[10px] text-muted-foreground", children: event.property })
84
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-mono text-[10px] text-muted-foreground", children: event.property })
81
85
  ] }),
82
- /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xs leading-relaxed text-muted-foreground", children: event.description }),
83
- /* @__PURE__ */ jsxRuntime.jsx(
84
- "div",
85
- {
86
- className: "flex flex-wrap gap-1.5",
87
- "aria-label": `${event.label} captured fields`,
88
- children: event.captures.map((capture) => /* @__PURE__ */ jsxRuntime.jsx(
89
- "span",
90
- {
91
- className: "rounded-full border border-border px-1.5 py-0.5 text-[10px] text-muted-foreground",
92
- children: capture
93
- },
94
- capture
95
- ))
96
- }
97
- )
86
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xs text-muted-foreground", children: event.description }),
87
+ /* @__PURE__ */ jsxRuntime.jsxs("p", { className: "text-[10px] text-muted-foreground/80", children: [
88
+ "Captures ",
89
+ event.captures.join(", ")
90
+ ] })
98
91
  ] }),
99
- /* @__PURE__ */ jsxRuntime.jsxs("label", { className: "space-y-1 text-xs font-medium text-muted-foreground", children: [
100
- /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "sr-only", children: [
101
- event.label,
102
- " level"
103
- ] }),
92
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-wrap items-center gap-density-2", children: [
104
93
  /* @__PURE__ */ jsxRuntime.jsx(
105
- select.Select,
94
+ SegmentedControl.SegmentedControl,
106
95
  {
107
96
  "aria-label": `${event.label} level`,
108
97
  value: level,
109
- disabled: readOnly,
110
- options: LEVEL_OPTIONS,
111
- onChange: (input) => updateOverride(
112
- event.property,
113
- input.target.value,
114
- event.default
115
- )
98
+ options: LEVEL_SEGMENTS.map((option) => ({
99
+ ...option,
100
+ disabled: readOnly
101
+ })),
102
+ onChange: (next) => updateOverride(event.property, next, event.default),
103
+ size: "sm",
104
+ wrap: true
116
105
  }
117
106
  ),
118
- /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "block text-[10px] font-normal", children: [
119
- "Default: ",
107
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-[10px] text-muted-foreground", children: [
108
+ "Default ",
120
109
  event.default
121
110
  ] })
122
111
  ] })
@@ -1 +1 @@
1
- {"version":3,"file":"ConnectionLoggingPolicy.cjs","sources":["../../src/components/ConnectionLoggingPolicy.tsx"],"sourcesContent":["import { useState } from \"react\";\nimport { cn } from \"../lib/utils\";\nimport { SegmentedControl } from \"./SegmentedControl\";\nimport { Select } from \"./select\";\nimport {\n CONNECTION_LOG_LEVELS,\n effectiveConnectionLogLevel,\n parseConnectionLoggingThreshold,\n visibleConnectionLogEvents,\n type ConnectionLogLevel,\n type ConnectionLoggingPolicyProps,\n type ConnectionLoggingThreshold,\n} from \"./ConnectionLoggingPolicy.model\";\n\nconst LEVEL_OPTIONS = CONNECTION_LOG_LEVELS.map((level) => ({\n value: level,\n label: level === \"off\" ? \"Off\" : level[0]?.toUpperCase() + level.slice(1),\n}));\n\nconst THRESHOLD_PROPERTY = \"log.slowThreshold\";\ntype PreviewFormat = \"pretty\" | \"json\";\n\nexport function ConnectionLoggingPolicy({\n definition,\n value = {},\n onChange,\n readOnly = false,\n className,\n}: ConnectionLoggingPolicyProps) {\n const [previewLevel, setPreviewLevel] = useState<ConnectionLogLevel>(\"debug\");\n const [previewFormat, setPreviewFormat] = useState<PreviewFormat>(\"pretty\");\n const threshold = parseConnectionLoggingThreshold(\n value[THRESHOLD_PROPERTY] ?? definition.slowThreshold,\n );\n const visibleEvents = visibleConnectionLogEvents(\n definition,\n value,\n previewLevel,\n );\n\n const updateOverride = (\n property: string,\n next: string,\n defaultValue: string,\n ) => {\n const updated = { ...value };\n if (next === defaultValue) delete updated[property];\n else updated[property] = next;\n onChange(updated);\n };\n\n return (\n <section\n className={cn(\n \"space-y-density-4 rounded-lg border border-border bg-card p-density-4\",\n className,\n )}\n >\n <header className=\"flex flex-wrap items-start justify-between gap-density-3\">\n <div className=\"space-y-1\">\n <h3 className=\"text-sm font-semibold text-foreground\">\n Connection logging\n </h3>\n <p className=\"max-w-3xl text-xs leading-relaxed text-muted-foreground\">\n Errors win over slow operations, then the provider-specific record.\n Payloads are bounded and credentials are sanitized before logging.\n </p>\n </div>\n <span className=\"rounded-full border border-border bg-muted px-2 py-1 text-[11px] font-medium uppercase tracking-wide text-muted-foreground\">\n {definition.family}\n </span>\n </header>\n\n <div className=\"grid gap-density-4 xl:grid-cols-[minmax(0,1.2fr)_minmax(22rem,0.8fr)]\">\n <div className=\"space-y-density-3\">\n <ThresholdControl\n label={definition.thresholdLabel}\n threshold={threshold}\n disabled={readOnly}\n onChange={(next) =>\n updateOverride(\n THRESHOLD_PROPERTY,\n `${next.amount}${next.unit}`,\n definition.slowThreshold,\n )\n }\n />\n\n <div className=\"overflow-hidden rounded-md border border-border\">\n {definition.events.map((event) => {\n const level = effectiveConnectionLogLevel(event, value);\n return (\n <div\n key={event.event}\n className=\"grid gap-density-3 border-b border-border p-density-3 last:border-b-0 md:grid-cols-[minmax(0,1fr)_8rem]\"\n >\n <div className=\"min-w-0 space-y-1.5\">\n <div className=\"flex flex-wrap items-center gap-2\">\n <span className=\"text-sm font-medium text-foreground\">\n {event.label}\n </span>\n <span className=\"rounded bg-muted px-1.5 py-0.5 font-mono text-[10px] text-muted-foreground\">\n {event.property}\n </span>\n </div>\n <p className=\"text-xs leading-relaxed text-muted-foreground\">\n {event.description}\n </p>\n <div\n className=\"flex flex-wrap gap-1.5\"\n aria-label={`${event.label} captured fields`}\n >\n {event.captures.map((capture) => (\n <span\n key={capture}\n className=\"rounded-full border border-border px-1.5 py-0.5 text-[10px] text-muted-foreground\"\n >\n {capture}\n </span>\n ))}\n </div>\n </div>\n <label className=\"space-y-1 text-xs font-medium text-muted-foreground\">\n <span className=\"sr-only\">{event.label} level</span>\n <Select\n aria-label={`${event.label} level`}\n value={level}\n disabled={readOnly}\n options={LEVEL_OPTIONS}\n onChange={(input) =>\n updateOverride(\n event.property,\n input.target.value,\n event.default,\n )\n }\n />\n <span className=\"block text-[10px] font-normal\">\n Default: {event.default}\n </span>\n </label>\n </div>\n );\n })}\n </div>\n </div>\n\n <aside className=\"min-w-0 space-y-density-3 rounded-md border border-border bg-background p-density-3\">\n <div className=\"flex flex-wrap items-end justify-between gap-density-2\">\n <div>\n <h4 className=\"text-sm font-semibold text-foreground\">\n What gets logged\n </h4>\n <p className=\"text-xs text-muted-foreground\">\n Cumulative records at the effective logger level.\n </p>\n </div>\n <div className=\"flex flex-wrap items-end gap-density-2\">\n <div className=\"space-y-1 text-xs font-medium text-muted-foreground\">\n Preview format\n <SegmentedControl<PreviewFormat>\n aria-label=\"Preview format\"\n value={previewFormat}\n size=\"sm\"\n options={[\n { id: \"pretty\", label: \"Pretty\" },\n { id: \"json\", label: \"JSON\" },\n ]}\n onChange={setPreviewFormat}\n />\n </div>\n <label className=\"w-36 space-y-1 text-xs font-medium text-muted-foreground\">\n Preview level\n <Select\n aria-label=\"Preview logger level\"\n value={previewLevel}\n options={LEVEL_OPTIONS}\n onChange={(event) =>\n setPreviewLevel(event.target.value as ConnectionLogLevel)\n }\n />\n </label>\n </div>\n </div>\n\n <div\n data-testid=\"connection-log-preview\"\n className=\"space-y-density-2\"\n >\n {visibleEvents.length === 0 ? (\n <div className=\"rounded-md border border-dashed border-border p-density-4 text-center text-xs text-muted-foreground\">\n No connection records are emitted at this level.\n </div>\n ) : (\n visibleEvents.map((event) => (\n <article\n key={event.event}\n data-testid=\"connection-log-preview-event\"\n className=\"overflow-hidden rounded-md border border-border\"\n >\n <div className=\"flex items-center justify-between gap-2 border-b border-border bg-muted/60 px-2.5 py-1.5\">\n <span className=\"text-xs font-medium text-foreground\">\n {event.label}\n </span>\n <span\n className={cn(\n \"font-mono text-[10px] font-semibold\",\n levelTone(effectiveConnectionLogLevel(event, value)),\n )}\n >\n {effectiveConnectionLogLevel(event, value)}\n </span>\n </div>\n <pre className=\"overflow-x-auto whitespace-pre-wrap break-words p-2.5 font-mono text-[11px] leading-relaxed text-foreground\">\n {previewFormat === \"pretty\"\n ? event.prettyExample\n : JSON.stringify(event.example, null, 2)}\n </pre>\n </article>\n ))\n )}\n </div>\n </aside>\n </div>\n </section>\n );\n}\n\nfunction ThresholdControl({\n label,\n threshold,\n disabled,\n onChange,\n}: {\n label: string;\n threshold: ConnectionLoggingThreshold;\n disabled: boolean;\n onChange: (next: ConnectionLoggingThreshold) => void;\n}) {\n return (\n <div className=\"flex flex-wrap items-end justify-between gap-density-3 rounded-md border border-border bg-muted/30 p-density-3\">\n <div>\n <div className=\"text-sm font-medium text-foreground\">{label}</div>\n <p className=\"text-xs text-muted-foreground\">\n A successful operation at or above this duration logs as slow.\n </p>\n </div>\n <div className=\"flex w-48 gap-2\">\n <input\n type=\"number\"\n min=\"0.001\"\n step=\"any\"\n aria-label=\"Slow threshold value\"\n value={threshold.amount}\n disabled={disabled}\n onChange={(event) => {\n if (Number(event.target.value) > 0)\n onChange({ ...threshold, amount: event.target.value });\n }}\n className=\"h-control-h min-w-0 flex-1 rounded-md border border-input bg-background px-control-px text-sm text-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring\"\n />\n <Select\n aria-label=\"Slow threshold unit\"\n value={threshold.unit}\n disabled={disabled}\n className=\"w-20\"\n options={[\n { value: \"ms\", label: \"ms\" },\n { value: \"s\", label: \"sec\" },\n { value: \"m\", label: \"min\" },\n { value: \"h\", label: \"hour\" },\n ]}\n onChange={(event) =>\n onChange({\n ...threshold,\n unit: event.target.value as ConnectionLoggingThreshold[\"unit\"],\n })\n }\n />\n </div>\n </div>\n );\n}\n\nfunction levelTone(level: ConnectionLogLevel) {\n switch (level) {\n case \"error\":\n return \"text-destructive\";\n case \"warn\":\n return \"text-warning-foreground\";\n case \"info\":\n return \"text-foreground\";\n case \"off\":\n return \"text-muted-foreground\";\n default:\n return \"text-primary\";\n }\n}\n"],"names":["CONNECTION_LOG_LEVELS","useState","parseConnectionLoggingThreshold","visibleConnectionLogEvents","jsxs","cn","jsx","effectiveConnectionLogLevel","Select","SegmentedControl"],"mappings":"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"}
1
+ {"version":3,"file":"ConnectionLoggingPolicy.cjs","sources":["../../src/components/ConnectionLoggingPolicy.tsx"],"sourcesContent":["import { useState } from \"react\";\nimport { cn } from \"../lib/utils\";\nimport { SegmentedControl } from \"./SegmentedControl\";\nimport { Select } from \"./select\";\nimport {\n CONNECTION_LOG_LEVELS,\n effectiveConnectionLogLevel,\n parseConnectionLoggingThreshold,\n visibleConnectionLogEvents,\n type ConnectionLogLevel,\n type ConnectionLoggingPolicyProps,\n type ConnectionLoggingThreshold,\n} from \"./ConnectionLoggingPolicy.model\";\n\nconst LEVEL_OPTIONS = CONNECTION_LOG_LEVELS.map((level) => ({\n value: level,\n label: level === \"off\" ? \"Off\" : level[0]?.toUpperCase() + level.slice(1),\n}));\nconst LEVEL_SEGMENTS = LEVEL_OPTIONS.map(({ value, label }) => ({\n id: value,\n label,\n}));\n\nconst THRESHOLD_PROPERTY = \"log.slowThreshold\";\ntype PreviewFormat = \"pretty\" | \"json\";\n\nexport function ConnectionLoggingPolicy({\n definition,\n value = {},\n onChange,\n readOnly = false,\n className,\n}: ConnectionLoggingPolicyProps) {\n const [previewLevel, setPreviewLevel] = useState<ConnectionLogLevel>(\"debug\");\n const [previewFormat, setPreviewFormat] = useState<PreviewFormat>(\"pretty\");\n const threshold = parseConnectionLoggingThreshold(\n value[THRESHOLD_PROPERTY] ?? definition.slowThreshold,\n );\n const visibleEvents = visibleConnectionLogEvents(\n definition,\n value,\n previewLevel,\n );\n\n const updateOverride = (\n property: string,\n next: string,\n defaultValue: string,\n ) => {\n const updated = { ...value };\n if (next === defaultValue) delete updated[property];\n else updated[property] = next;\n onChange(updated);\n };\n\n return (\n <section\n className={cn(\n \"space-y-density-4 rounded-lg border border-border bg-card p-density-4\",\n className,\n )}\n >\n <header className=\"flex flex-wrap items-start justify-between gap-density-3\">\n <div className=\"space-y-1\">\n <h3 className=\"text-sm font-semibold text-foreground\">\n Connection logging\n </h3>\n <p className=\"max-w-3xl text-xs leading-relaxed text-muted-foreground\">\n Errors win over slow operations, then the provider-specific record.\n Payloads are bounded and credentials are sanitized before logging.\n </p>\n </div>\n <span className=\"font-mono text-[11px] font-medium uppercase tracking-wide text-muted-foreground\">\n {definition.family}\n </span>\n </header>\n\n <div className=\"grid gap-density-4 xl:grid-cols-[minmax(0,1.2fr)_minmax(22rem,0.8fr)]\">\n <div className=\"space-y-density-3\">\n <ThresholdControl\n label={definition.thresholdLabel}\n threshold={threshold}\n disabled={readOnly}\n onChange={(next) =>\n updateOverride(\n THRESHOLD_PROPERTY,\n `${next.amount}${next.unit}`,\n definition.slowThreshold,\n )\n }\n />\n\n <div className=\"overflow-hidden rounded-md border border-border\">\n {definition.events.map((event) => {\n const level = effectiveConnectionLogLevel(event, value);\n return (\n <div\n key={event.event}\n className=\"grid gap-density-2 border-b border-border px-density-3 py-density-2 last:border-b-0 xl:grid-cols-[minmax(12rem,1fr)_auto] xl:items-center\"\n >\n <div className=\"min-w-0 space-y-1\">\n <div className=\"flex flex-wrap items-center gap-2\">\n <span className=\"text-sm font-medium text-foreground\">\n {event.label}\n </span>\n <span className=\"font-mono text-[10px] text-muted-foreground\">\n {event.property}\n </span>\n </div>\n <p className=\"text-xs text-muted-foreground\">{event.description}</p>\n <p className=\"text-[10px] text-muted-foreground/80\">\n Captures {event.captures.join(\", \")}\n </p>\n </div>\n <div className=\"flex flex-wrap items-center gap-density-2\">\n <SegmentedControl<ConnectionLogLevel>\n aria-label={`${event.label} level`}\n value={level}\n options={LEVEL_SEGMENTS.map((option) => ({\n ...option,\n disabled: readOnly,\n }))}\n onChange={(next) =>\n updateOverride(event.property, next, event.default)\n }\n size=\"sm\"\n wrap\n />\n <span className=\"text-[10px] text-muted-foreground\">\n Default {event.default}\n </span>\n </div>\n </div>\n );\n })}\n </div>\n </div>\n\n <aside className=\"min-w-0 space-y-density-3 rounded-md border border-border bg-background p-density-3\">\n <div className=\"flex flex-wrap items-end justify-between gap-density-2\">\n <div>\n <h4 className=\"text-sm font-semibold text-foreground\">\n What gets logged\n </h4>\n <p className=\"text-xs text-muted-foreground\">\n Cumulative records at the effective logger level.\n </p>\n </div>\n <div className=\"flex flex-wrap items-end gap-density-2\">\n <div className=\"space-y-1 text-xs font-medium text-muted-foreground\">\n Preview format\n <SegmentedControl<PreviewFormat>\n aria-label=\"Preview format\"\n value={previewFormat}\n size=\"sm\"\n options={[\n { id: \"pretty\", label: \"Pretty\" },\n { id: \"json\", label: \"JSON\" },\n ]}\n onChange={setPreviewFormat}\n />\n </div>\n <label className=\"w-36 space-y-1 text-xs font-medium text-muted-foreground\">\n Preview level\n <Select\n aria-label=\"Preview logger level\"\n value={previewLevel}\n options={LEVEL_OPTIONS}\n onChange={(event) =>\n setPreviewLevel(event.target.value as ConnectionLogLevel)\n }\n />\n </label>\n </div>\n </div>\n\n <div\n data-testid=\"connection-log-preview\"\n className=\"space-y-density-2\"\n >\n {visibleEvents.length === 0 ? (\n <div className=\"rounded-md border border-dashed border-border p-density-4 text-center text-xs text-muted-foreground\">\n No connection records are emitted at this level.\n </div>\n ) : (\n visibleEvents.map((event) => (\n <article\n key={event.event}\n data-testid=\"connection-log-preview-event\"\n className=\"overflow-hidden rounded-md border border-border\"\n >\n <div className=\"flex items-center justify-between gap-2 border-b border-border bg-muted/60 px-2.5 py-1.5\">\n <span className=\"text-xs font-medium text-foreground\">\n {event.label}\n </span>\n <span\n className={cn(\n \"font-mono text-[10px] font-semibold\",\n levelTone(effectiveConnectionLogLevel(event, value)),\n )}\n >\n {effectiveConnectionLogLevel(event, value)}\n </span>\n </div>\n <pre className=\"overflow-x-auto whitespace-pre-wrap break-words p-2.5 font-mono text-[11px] leading-relaxed text-foreground\">\n {previewFormat === \"pretty\"\n ? event.prettyExample\n : JSON.stringify(event.example, null, 2)}\n </pre>\n </article>\n ))\n )}\n </div>\n </aside>\n </div>\n </section>\n );\n}\n\nfunction ThresholdControl({\n label,\n threshold,\n disabled,\n onChange,\n}: {\n label: string;\n threshold: ConnectionLoggingThreshold;\n disabled: boolean;\n onChange: (next: ConnectionLoggingThreshold) => void;\n}) {\n return (\n <div className=\"flex flex-wrap items-end justify-between gap-density-3 rounded-md border border-border bg-muted/30 p-density-3\">\n <div>\n <div className=\"text-sm font-medium text-foreground\">{label}</div>\n <p className=\"text-xs text-muted-foreground\">\n A successful operation at or above this duration logs as slow.\n </p>\n </div>\n <div className=\"flex w-48 gap-2\">\n <input\n type=\"number\"\n min=\"0.001\"\n step=\"any\"\n aria-label=\"Slow threshold value\"\n value={threshold.amount}\n disabled={disabled}\n onChange={(event) => {\n if (Number(event.target.value) > 0)\n onChange({ ...threshold, amount: event.target.value });\n }}\n className=\"h-control-h min-w-0 flex-1 rounded-md border border-input bg-background px-control-px text-sm text-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring\"\n />\n <Select\n aria-label=\"Slow threshold unit\"\n value={threshold.unit}\n disabled={disabled}\n className=\"w-20\"\n options={[\n { value: \"ms\", label: \"ms\" },\n { value: \"s\", label: \"sec\" },\n { value: \"m\", label: \"min\" },\n { value: \"h\", label: \"hour\" },\n ]}\n onChange={(event) =>\n onChange({\n ...threshold,\n unit: event.target.value as ConnectionLoggingThreshold[\"unit\"],\n })\n }\n />\n </div>\n </div>\n );\n}\n\nfunction levelTone(level: ConnectionLogLevel) {\n switch (level) {\n case \"error\":\n return \"text-destructive\";\n case \"warn\":\n return \"text-warning-foreground\";\n case \"info\":\n return \"text-foreground\";\n case \"off\":\n return \"text-muted-foreground\";\n default:\n return \"text-primary\";\n }\n}\n"],"names":["CONNECTION_LOG_LEVELS","useState","parseConnectionLoggingThreshold","visibleConnectionLogEvents","jsxs","cn","jsx","effectiveConnectionLogLevel","SegmentedControl","Select"],"mappings":";;;;;;;;AAcA,MAAM,gBAAgBA,8BAAAA,sBAAsB,IAAI,CAAC,UAAA;;AAAW;AAAA,IAC1D,OAAO;AAAA,IACP,OAAO,UAAU,QAAQ,UAAQ,WAAM,CAAC,MAAP,mBAAU,iBAAgB,MAAM,MAAM,CAAC;AAAA,EAC1E;AAAA,CAAE;AACF,MAAM,iBAAiB,cAAc,IAAI,CAAC,EAAE,OAAO,aAAa;AAAA,EAC9D,IAAI;AAAA,EACJ;AACF,EAAE;AAEF,MAAM,qBAAqB;AAGpB,SAAS,wBAAwB;AAAA,EACtC;AAAA,EACA,QAAQ,CAAA;AAAA,EACR;AAAA,EACA,WAAW;AAAA,EACX;AACF,GAAiC;AAC/B,QAAM,CAAC,cAAc,eAAe,IAAIC,MAAAA,SAA6B,OAAO;AAC5E,QAAM,CAAC,eAAe,gBAAgB,IAAIA,MAAAA,SAAwB,QAAQ;AAC1E,QAAM,YAAYC,8BAAAA;AAAAA,IAChB,MAAM,kBAAkB,KAAK,WAAW;AAAA,EAAA;AAE1C,QAAM,gBAAgBC,8BAAAA;AAAAA,IACpB;AAAA,IACA;AAAA,IACA;AAAA,EAAA;AAGF,QAAM,iBAAiB,CACrB,UACA,MACA,iBACG;AACH,UAAM,UAAU,EAAE,GAAG,MAAA;AACrB,QAAI,SAAS,aAAc,QAAO,QAAQ,QAAQ;AAAA,QAC7C,SAAQ,QAAQ,IAAI;AACzB,aAAS,OAAO;AAAA,EAClB;AAEA,SACEC,2BAAAA;AAAAA,IAAC;AAAA,IAAA;AAAA,MACC,WAAWC,MAAAA;AAAAA,QACT;AAAA,QACA;AAAA,MAAA;AAAA,MAGF,UAAA;AAAA,QAAAD,2BAAAA,KAAC,UAAA,EAAO,WAAU,4DAChB,UAAA;AAAA,UAAAA,2BAAAA,KAAC,OAAA,EAAI,WAAU,aACb,UAAA;AAAA,YAAAE,2BAAAA,IAAC,MAAA,EAAG,WAAU,yCAAwC,UAAA,sBAEtD;AAAA,YACAA,2BAAAA,IAAC,KAAA,EAAE,WAAU,2DAA0D,UAAA,yIAAA,CAGvE;AAAA,UAAA,GACF;AAAA,UACAA,2BAAAA,IAAC,QAAA,EAAK,WAAU,mFACb,qBAAW,OAAA,CACd;AAAA,QAAA,GACF;AAAA,QAEAF,2BAAAA,KAAC,OAAA,EAAI,WAAU,yEACb,UAAA;AAAA,UAAAA,2BAAAA,KAAC,OAAA,EAAI,WAAU,qBACb,UAAA;AAAA,YAAAE,2BAAAA;AAAAA,cAAC;AAAA,cAAA;AAAA,gBACC,OAAO,WAAW;AAAA,gBAClB;AAAA,gBACA,UAAU;AAAA,gBACV,UAAU,CAAC,SACT;AAAA,kBACE;AAAA,kBACA,GAAG,KAAK,MAAM,GAAG,KAAK,IAAI;AAAA,kBAC1B,WAAW;AAAA,gBAAA;AAAA,cACb;AAAA,YAAA;AAAA,YAIJA,+BAAC,SAAI,WAAU,mDACZ,qBAAW,OAAO,IAAI,CAAC,UAAU;AAChC,oBAAM,QAAQC,8BAAAA,4BAA4B,OAAO,KAAK;AACtD,qBACEH,2BAAAA;AAAAA,gBAAC;AAAA,gBAAA;AAAA,kBAEC,WAAU;AAAA,kBAEV,UAAA;AAAA,oBAAAA,2BAAAA,KAAC,OAAA,EAAI,WAAU,qBACb,UAAA;AAAA,sBAAAA,2BAAAA,KAAC,OAAA,EAAI,WAAU,qCACb,UAAA;AAAA,wBAAAE,2BAAAA,IAAC,QAAA,EAAK,WAAU,uCACb,UAAA,MAAM,OACT;AAAA,wBACAA,2BAAAA,IAAC,QAAA,EAAK,WAAU,+CACb,gBAAM,SAAA,CACT;AAAA,sBAAA,GACF;AAAA,sBACAA,2BAAAA,IAAC,KAAA,EAAE,WAAU,iCAAiC,gBAAM,aAAY;AAAA,sBAChEF,2BAAAA,KAAC,KAAA,EAAE,WAAU,wCAAuC,UAAA;AAAA,wBAAA;AAAA,wBACxC,MAAM,SAAS,KAAK,IAAI;AAAA,sBAAA,EAAA,CACpC;AAAA,oBAAA,GACF;AAAA,oBACAA,2BAAAA,KAAC,OAAA,EAAI,WAAU,6CACb,UAAA;AAAA,sBAAAE,2BAAAA;AAAAA,wBAACE,iBAAAA;AAAAA,wBAAA;AAAA,0BACC,cAAY,GAAG,MAAM,KAAK;AAAA,0BAC1B,OAAO;AAAA,0BACP,SAAS,eAAe,IAAI,CAAC,YAAY;AAAA,4BACvC,GAAG;AAAA,4BACH,UAAU;AAAA,0BAAA,EACV;AAAA,0BACF,UAAU,CAAC,SACT,eAAe,MAAM,UAAU,MAAM,MAAM,OAAO;AAAA,0BAEpD,MAAK;AAAA,0BACL,MAAI;AAAA,wBAAA;AAAA,sBAAA;AAAA,sBAENJ,2BAAAA,KAAC,QAAA,EAAK,WAAU,qCAAoC,UAAA;AAAA,wBAAA;AAAA,wBACzC,MAAM;AAAA,sBAAA,EAAA,CACjB;AAAA,oBAAA,EAAA,CACF;AAAA,kBAAA;AAAA,gBAAA;AAAA,gBAlCK,MAAM;AAAA,cAAA;AAAA,YAqCjB,CAAC,EAAA,CACH;AAAA,UAAA,GACF;AAAA,UAEAA,2BAAAA,KAAC,SAAA,EAAM,WAAU,uFACf,UAAA;AAAA,YAAAA,2BAAAA,KAAC,OAAA,EAAI,WAAU,0DACb,UAAA;AAAA,cAAAA,gCAAC,OAAA,EACC,UAAA;AAAA,gBAAAE,2BAAAA,IAAC,MAAA,EAAG,WAAU,yCAAwC,UAAA,oBAEtD;AAAA,gBACAA,2BAAAA,IAAC,KAAA,EAAE,WAAU,iCAAgC,UAAA,oDAAA,CAE7C;AAAA,cAAA,GACF;AAAA,cACAF,2BAAAA,KAAC,OAAA,EAAI,WAAU,0CACb,UAAA;AAAA,gBAAAA,2BAAAA,KAAC,OAAA,EAAI,WAAU,uDAAsD,UAAA;AAAA,kBAAA;AAAA,kBAEnEE,2BAAAA;AAAAA,oBAACE,iBAAAA;AAAAA,oBAAA;AAAA,sBACC,cAAW;AAAA,sBACX,OAAO;AAAA,sBACP,MAAK;AAAA,sBACL,SAAS;AAAA,wBACP,EAAE,IAAI,UAAU,OAAO,SAAA;AAAA,wBACvB,EAAE,IAAI,QAAQ,OAAO,OAAA;AAAA,sBAAO;AAAA,sBAE9B,UAAU;AAAA,oBAAA;AAAA,kBAAA;AAAA,gBACZ,GACF;AAAA,gBACAJ,2BAAAA,KAAC,SAAA,EAAM,WAAU,4DAA2D,UAAA;AAAA,kBAAA;AAAA,kBAE1EE,2BAAAA;AAAAA,oBAACG,OAAAA;AAAAA,oBAAA;AAAA,sBACC,cAAW;AAAA,sBACX,OAAO;AAAA,sBACP,SAAS;AAAA,sBACT,UAAU,CAAC,UACT,gBAAgB,MAAM,OAAO,KAA2B;AAAA,oBAAA;AAAA,kBAAA;AAAA,gBAE5D,EAAA,CACF;AAAA,cAAA,EAAA,CACF;AAAA,YAAA,GACF;AAAA,YAEAH,2BAAAA;AAAAA,cAAC;AAAA,cAAA;AAAA,gBACC,eAAY;AAAA,gBACZ,WAAU;AAAA,gBAET,UAAA,cAAc,WAAW,IACxBA,2BAAAA,IAAC,OAAA,EAAI,WAAU,uGAAsG,UAAA,mDAAA,CAErH,IAEA,cAAc,IAAI,CAAC,UACjBF,2BAAAA;AAAAA,kBAAC;AAAA,kBAAA;AAAA,oBAEC,eAAY;AAAA,oBACZ,WAAU;AAAA,oBAEV,UAAA;AAAA,sBAAAA,2BAAAA,KAAC,OAAA,EAAI,WAAU,4FACb,UAAA;AAAA,wBAAAE,2BAAAA,IAAC,QAAA,EAAK,WAAU,uCACb,UAAA,MAAM,OACT;AAAA,wBACAA,2BAAAA;AAAAA,0BAAC;AAAA,0BAAA;AAAA,4BACC,WAAWD,MAAAA;AAAAA,8BACT;AAAA,8BACA,UAAUE,8BAAAA,4BAA4B,OAAO,KAAK,CAAC;AAAA,4BAAA;AAAA,4BAGpD,UAAAA,8BAAAA,4BAA4B,OAAO,KAAK;AAAA,0BAAA;AAAA,wBAAA;AAAA,sBAC3C,GACF;AAAA,sBACAD,2BAAAA,IAAC,OAAA,EAAI,WAAU,+GACZ,4BAAkB,WACf,MAAM,gBACN,KAAK,UAAU,MAAM,SAAS,MAAM,CAAC,EAAA,CAC3C;AAAA,oBAAA;AAAA,kBAAA;AAAA,kBArBK,MAAM;AAAA,gBAAA,CAuBd;AAAA,cAAA;AAAA,YAAA;AAAA,UAEL,EAAA,CACF;AAAA,QAAA,EAAA,CACF;AAAA,MAAA;AAAA,IAAA;AAAA,EAAA;AAGN;AAEA,SAAS,iBAAiB;AAAA,EACxB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAKG;AACD,SACEF,2BAAAA,KAAC,OAAA,EAAI,WAAU,kHACb,UAAA;AAAA,IAAAA,gCAAC,OAAA,EACC,UAAA;AAAA,MAAAE,2BAAAA,IAAC,OAAA,EAAI,WAAU,uCAAuC,UAAA,OAAM;AAAA,MAC5DA,2BAAAA,IAAC,KAAA,EAAE,WAAU,iCAAgC,UAAA,iEAAA,CAE7C;AAAA,IAAA,GACF;AAAA,IACAF,2BAAAA,KAAC,OAAA,EAAI,WAAU,mBACb,UAAA;AAAA,MAAAE,2BAAAA;AAAAA,QAAC;AAAA,QAAA;AAAA,UACC,MAAK;AAAA,UACL,KAAI;AAAA,UACJ,MAAK;AAAA,UACL,cAAW;AAAA,UACX,OAAO,UAAU;AAAA,UACjB;AAAA,UACA,UAAU,CAAC,UAAU;AACnB,gBAAI,OAAO,MAAM,OAAO,KAAK,IAAI;AAC/B,uBAAS,EAAE,GAAG,WAAW,QAAQ,MAAM,OAAO,OAAO;AAAA,UACzD;AAAA,UACA,WAAU;AAAA,QAAA;AAAA,MAAA;AAAA,MAEZA,2BAAAA;AAAAA,QAACG,OAAAA;AAAAA,QAAA;AAAA,UACC,cAAW;AAAA,UACX,OAAO,UAAU;AAAA,UACjB;AAAA,UACA,WAAU;AAAA,UACV,SAAS;AAAA,YACP,EAAE,OAAO,MAAM,OAAO,KAAA;AAAA,YACtB,EAAE,OAAO,KAAK,OAAO,MAAA;AAAA,YACrB,EAAE,OAAO,KAAK,OAAO,MAAA;AAAA,YACrB,EAAE,OAAO,KAAK,OAAO,OAAA;AAAA,UAAO;AAAA,UAE9B,UAAU,CAAC,UACT,SAAS;AAAA,YACP,GAAG;AAAA,YACH,MAAM,MAAM,OAAO;AAAA,UAAA,CACpB;AAAA,QAAA;AAAA,MAAA;AAAA,IAEL,EAAA,CACF;AAAA,EAAA,GACF;AAEJ;AAEA,SAAS,UAAU,OAA2B;AAC5C,UAAQ,OAAA;AAAA,IACN,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO;AAAA,IACT;AACE,aAAO;AAAA,EAAA;AAEb;;"}
@@ -1 +1 @@
1
- {"version":3,"file":"ConnectionLoggingPolicy.d.ts","sourceRoot":"","sources":["../../src/components/ConnectionLoggingPolicy.tsx"],"names":[],"mappings":"AAIA,OAAO,EAML,KAAK,4BAA4B,EAElC,MAAM,iCAAiC,CAAC;AAUzC,wBAAgB,uBAAuB,CAAC,EACtC,UAAU,EACV,KAAU,EACV,QAAQ,EACR,QAAgB,EAChB,SAAS,GACV,EAAE,4BAA4B,+BAsM9B"}
1
+ {"version":3,"file":"ConnectionLoggingPolicy.d.ts","sourceRoot":"","sources":["../../src/components/ConnectionLoggingPolicy.tsx"],"names":[],"mappings":"AAIA,OAAO,EAML,KAAK,4BAA4B,EAElC,MAAM,iCAAiC,CAAC;AAczC,wBAAgB,uBAAuB,CAAC,EACtC,UAAU,EACV,KAAU,EACV,QAAQ,EACR,QAAgB,EAChB,SAAS,GACV,EAAE,4BAA4B,+BAyL9B"}
@@ -11,6 +11,10 @@ const LEVEL_OPTIONS = CONNECTION_LOG_LEVELS.map((level) => {
11
11
  label: level === "off" ? "Off" : ((_a = level[0]) == null ? void 0 : _a.toUpperCase()) + level.slice(1)
12
12
  };
13
13
  });
14
+ const LEVEL_SEGMENTS = LEVEL_OPTIONS.map(({ value, label }) => ({
15
+ id: value,
16
+ label
17
+ }));
14
18
  const THRESHOLD_PROPERTY = "log.slowThreshold";
15
19
  function ConnectionLoggingPolicy({
16
20
  definition,
@@ -48,7 +52,7 @@ function ConnectionLoggingPolicy({
48
52
  /* @__PURE__ */ jsx("h3", { className: "text-sm font-semibold text-foreground", children: "Connection logging" }),
49
53
  /* @__PURE__ */ jsx("p", { className: "max-w-3xl text-xs leading-relaxed text-muted-foreground", children: "Errors win over slow operations, then the provider-specific record. Payloads are bounded and credentials are sanitized before logging." })
50
54
  ] }),
51
- /* @__PURE__ */ jsx("span", { className: "rounded-full border border-border bg-muted px-2 py-1 text-[11px] font-medium uppercase tracking-wide text-muted-foreground", children: definition.family })
55
+ /* @__PURE__ */ jsx("span", { className: "font-mono text-[11px] font-medium uppercase tracking-wide text-muted-foreground", children: definition.family })
52
56
  ] }),
53
57
  /* @__PURE__ */ jsxs("div", { className: "grid gap-density-4 xl:grid-cols-[minmax(0,1.2fr)_minmax(22rem,0.8fr)]", children: [
54
58
  /* @__PURE__ */ jsxs("div", { className: "space-y-density-3", children: [
@@ -70,51 +74,36 @@ function ConnectionLoggingPolicy({
70
74
  return /* @__PURE__ */ jsxs(
71
75
  "div",
72
76
  {
73
- className: "grid gap-density-3 border-b border-border p-density-3 last:border-b-0 md:grid-cols-[minmax(0,1fr)_8rem]",
77
+ className: "grid gap-density-2 border-b border-border px-density-3 py-density-2 last:border-b-0 xl:grid-cols-[minmax(12rem,1fr)_auto] xl:items-center",
74
78
  children: [
75
- /* @__PURE__ */ jsxs("div", { className: "min-w-0 space-y-1.5", children: [
79
+ /* @__PURE__ */ jsxs("div", { className: "min-w-0 space-y-1", children: [
76
80
  /* @__PURE__ */ jsxs("div", { className: "flex flex-wrap items-center gap-2", children: [
77
81
  /* @__PURE__ */ jsx("span", { className: "text-sm font-medium text-foreground", children: event.label }),
78
- /* @__PURE__ */ jsx("span", { className: "rounded bg-muted px-1.5 py-0.5 font-mono text-[10px] text-muted-foreground", children: event.property })
82
+ /* @__PURE__ */ jsx("span", { className: "font-mono text-[10px] text-muted-foreground", children: event.property })
79
83
  ] }),
80
- /* @__PURE__ */ jsx("p", { className: "text-xs leading-relaxed text-muted-foreground", children: event.description }),
81
- /* @__PURE__ */ jsx(
82
- "div",
83
- {
84
- className: "flex flex-wrap gap-1.5",
85
- "aria-label": `${event.label} captured fields`,
86
- children: event.captures.map((capture) => /* @__PURE__ */ jsx(
87
- "span",
88
- {
89
- className: "rounded-full border border-border px-1.5 py-0.5 text-[10px] text-muted-foreground",
90
- children: capture
91
- },
92
- capture
93
- ))
94
- }
95
- )
84
+ /* @__PURE__ */ jsx("p", { className: "text-xs text-muted-foreground", children: event.description }),
85
+ /* @__PURE__ */ jsxs("p", { className: "text-[10px] text-muted-foreground/80", children: [
86
+ "Captures ",
87
+ event.captures.join(", ")
88
+ ] })
96
89
  ] }),
97
- /* @__PURE__ */ jsxs("label", { className: "space-y-1 text-xs font-medium text-muted-foreground", children: [
98
- /* @__PURE__ */ jsxs("span", { className: "sr-only", children: [
99
- event.label,
100
- " level"
101
- ] }),
90
+ /* @__PURE__ */ jsxs("div", { className: "flex flex-wrap items-center gap-density-2", children: [
102
91
  /* @__PURE__ */ jsx(
103
- Select,
92
+ SegmentedControl,
104
93
  {
105
94
  "aria-label": `${event.label} level`,
106
95
  value: level,
107
- disabled: readOnly,
108
- options: LEVEL_OPTIONS,
109
- onChange: (input) => updateOverride(
110
- event.property,
111
- input.target.value,
112
- event.default
113
- )
96
+ options: LEVEL_SEGMENTS.map((option) => ({
97
+ ...option,
98
+ disabled: readOnly
99
+ })),
100
+ onChange: (next) => updateOverride(event.property, next, event.default),
101
+ size: "sm",
102
+ wrap: true
114
103
  }
115
104
  ),
116
- /* @__PURE__ */ jsxs("span", { className: "block text-[10px] font-normal", children: [
117
- "Default: ",
105
+ /* @__PURE__ */ jsxs("span", { className: "text-[10px] text-muted-foreground", children: [
106
+ "Default ",
118
107
  event.default
119
108
  ] })
120
109
  ] })
@@ -1 +1 @@
1
- {"version":3,"file":"ConnectionLoggingPolicy.js","sources":["../../src/components/ConnectionLoggingPolicy.tsx"],"sourcesContent":["import { useState } from \"react\";\nimport { cn } from \"../lib/utils\";\nimport { SegmentedControl } from \"./SegmentedControl\";\nimport { Select } from \"./select\";\nimport {\n CONNECTION_LOG_LEVELS,\n effectiveConnectionLogLevel,\n parseConnectionLoggingThreshold,\n visibleConnectionLogEvents,\n type ConnectionLogLevel,\n type ConnectionLoggingPolicyProps,\n type ConnectionLoggingThreshold,\n} from \"./ConnectionLoggingPolicy.model\";\n\nconst LEVEL_OPTIONS = CONNECTION_LOG_LEVELS.map((level) => ({\n value: level,\n label: level === \"off\" ? \"Off\" : level[0]?.toUpperCase() + level.slice(1),\n}));\n\nconst THRESHOLD_PROPERTY = \"log.slowThreshold\";\ntype PreviewFormat = \"pretty\" | \"json\";\n\nexport function ConnectionLoggingPolicy({\n definition,\n value = {},\n onChange,\n readOnly = false,\n className,\n}: ConnectionLoggingPolicyProps) {\n const [previewLevel, setPreviewLevel] = useState<ConnectionLogLevel>(\"debug\");\n const [previewFormat, setPreviewFormat] = useState<PreviewFormat>(\"pretty\");\n const threshold = parseConnectionLoggingThreshold(\n value[THRESHOLD_PROPERTY] ?? definition.slowThreshold,\n );\n const visibleEvents = visibleConnectionLogEvents(\n definition,\n value,\n previewLevel,\n );\n\n const updateOverride = (\n property: string,\n next: string,\n defaultValue: string,\n ) => {\n const updated = { ...value };\n if (next === defaultValue) delete updated[property];\n else updated[property] = next;\n onChange(updated);\n };\n\n return (\n <section\n className={cn(\n \"space-y-density-4 rounded-lg border border-border bg-card p-density-4\",\n className,\n )}\n >\n <header className=\"flex flex-wrap items-start justify-between gap-density-3\">\n <div className=\"space-y-1\">\n <h3 className=\"text-sm font-semibold text-foreground\">\n Connection logging\n </h3>\n <p className=\"max-w-3xl text-xs leading-relaxed text-muted-foreground\">\n Errors win over slow operations, then the provider-specific record.\n Payloads are bounded and credentials are sanitized before logging.\n </p>\n </div>\n <span className=\"rounded-full border border-border bg-muted px-2 py-1 text-[11px] font-medium uppercase tracking-wide text-muted-foreground\">\n {definition.family}\n </span>\n </header>\n\n <div className=\"grid gap-density-4 xl:grid-cols-[minmax(0,1.2fr)_minmax(22rem,0.8fr)]\">\n <div className=\"space-y-density-3\">\n <ThresholdControl\n label={definition.thresholdLabel}\n threshold={threshold}\n disabled={readOnly}\n onChange={(next) =>\n updateOverride(\n THRESHOLD_PROPERTY,\n `${next.amount}${next.unit}`,\n definition.slowThreshold,\n )\n }\n />\n\n <div className=\"overflow-hidden rounded-md border border-border\">\n {definition.events.map((event) => {\n const level = effectiveConnectionLogLevel(event, value);\n return (\n <div\n key={event.event}\n className=\"grid gap-density-3 border-b border-border p-density-3 last:border-b-0 md:grid-cols-[minmax(0,1fr)_8rem]\"\n >\n <div className=\"min-w-0 space-y-1.5\">\n <div className=\"flex flex-wrap items-center gap-2\">\n <span className=\"text-sm font-medium text-foreground\">\n {event.label}\n </span>\n <span className=\"rounded bg-muted px-1.5 py-0.5 font-mono text-[10px] text-muted-foreground\">\n {event.property}\n </span>\n </div>\n <p className=\"text-xs leading-relaxed text-muted-foreground\">\n {event.description}\n </p>\n <div\n className=\"flex flex-wrap gap-1.5\"\n aria-label={`${event.label} captured fields`}\n >\n {event.captures.map((capture) => (\n <span\n key={capture}\n className=\"rounded-full border border-border px-1.5 py-0.5 text-[10px] text-muted-foreground\"\n >\n {capture}\n </span>\n ))}\n </div>\n </div>\n <label className=\"space-y-1 text-xs font-medium text-muted-foreground\">\n <span className=\"sr-only\">{event.label} level</span>\n <Select\n aria-label={`${event.label} level`}\n value={level}\n disabled={readOnly}\n options={LEVEL_OPTIONS}\n onChange={(input) =>\n updateOverride(\n event.property,\n input.target.value,\n event.default,\n )\n }\n />\n <span className=\"block text-[10px] font-normal\">\n Default: {event.default}\n </span>\n </label>\n </div>\n );\n })}\n </div>\n </div>\n\n <aside className=\"min-w-0 space-y-density-3 rounded-md border border-border bg-background p-density-3\">\n <div className=\"flex flex-wrap items-end justify-between gap-density-2\">\n <div>\n <h4 className=\"text-sm font-semibold text-foreground\">\n What gets logged\n </h4>\n <p className=\"text-xs text-muted-foreground\">\n Cumulative records at the effective logger level.\n </p>\n </div>\n <div className=\"flex flex-wrap items-end gap-density-2\">\n <div className=\"space-y-1 text-xs font-medium text-muted-foreground\">\n Preview format\n <SegmentedControl<PreviewFormat>\n aria-label=\"Preview format\"\n value={previewFormat}\n size=\"sm\"\n options={[\n { id: \"pretty\", label: \"Pretty\" },\n { id: \"json\", label: \"JSON\" },\n ]}\n onChange={setPreviewFormat}\n />\n </div>\n <label className=\"w-36 space-y-1 text-xs font-medium text-muted-foreground\">\n Preview level\n <Select\n aria-label=\"Preview logger level\"\n value={previewLevel}\n options={LEVEL_OPTIONS}\n onChange={(event) =>\n setPreviewLevel(event.target.value as ConnectionLogLevel)\n }\n />\n </label>\n </div>\n </div>\n\n <div\n data-testid=\"connection-log-preview\"\n className=\"space-y-density-2\"\n >\n {visibleEvents.length === 0 ? (\n <div className=\"rounded-md border border-dashed border-border p-density-4 text-center text-xs text-muted-foreground\">\n No connection records are emitted at this level.\n </div>\n ) : (\n visibleEvents.map((event) => (\n <article\n key={event.event}\n data-testid=\"connection-log-preview-event\"\n className=\"overflow-hidden rounded-md border border-border\"\n >\n <div className=\"flex items-center justify-between gap-2 border-b border-border bg-muted/60 px-2.5 py-1.5\">\n <span className=\"text-xs font-medium text-foreground\">\n {event.label}\n </span>\n <span\n className={cn(\n \"font-mono text-[10px] font-semibold\",\n levelTone(effectiveConnectionLogLevel(event, value)),\n )}\n >\n {effectiveConnectionLogLevel(event, value)}\n </span>\n </div>\n <pre className=\"overflow-x-auto whitespace-pre-wrap break-words p-2.5 font-mono text-[11px] leading-relaxed text-foreground\">\n {previewFormat === \"pretty\"\n ? event.prettyExample\n : JSON.stringify(event.example, null, 2)}\n </pre>\n </article>\n ))\n )}\n </div>\n </aside>\n </div>\n </section>\n );\n}\n\nfunction ThresholdControl({\n label,\n threshold,\n disabled,\n onChange,\n}: {\n label: string;\n threshold: ConnectionLoggingThreshold;\n disabled: boolean;\n onChange: (next: ConnectionLoggingThreshold) => void;\n}) {\n return (\n <div className=\"flex flex-wrap items-end justify-between gap-density-3 rounded-md border border-border bg-muted/30 p-density-3\">\n <div>\n <div className=\"text-sm font-medium text-foreground\">{label}</div>\n <p className=\"text-xs text-muted-foreground\">\n A successful operation at or above this duration logs as slow.\n </p>\n </div>\n <div className=\"flex w-48 gap-2\">\n <input\n type=\"number\"\n min=\"0.001\"\n step=\"any\"\n aria-label=\"Slow threshold value\"\n value={threshold.amount}\n disabled={disabled}\n onChange={(event) => {\n if (Number(event.target.value) > 0)\n onChange({ ...threshold, amount: event.target.value });\n }}\n className=\"h-control-h min-w-0 flex-1 rounded-md border border-input bg-background px-control-px text-sm text-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring\"\n />\n <Select\n aria-label=\"Slow threshold unit\"\n value={threshold.unit}\n disabled={disabled}\n className=\"w-20\"\n options={[\n { value: \"ms\", label: \"ms\" },\n { value: \"s\", label: \"sec\" },\n { value: \"m\", label: \"min\" },\n { value: \"h\", label: \"hour\" },\n ]}\n onChange={(event) =>\n onChange({\n ...threshold,\n unit: event.target.value as ConnectionLoggingThreshold[\"unit\"],\n })\n }\n />\n </div>\n </div>\n );\n}\n\nfunction levelTone(level: ConnectionLogLevel) {\n switch (level) {\n case \"error\":\n return \"text-destructive\";\n case \"warn\":\n return \"text-warning-foreground\";\n case \"info\":\n return \"text-foreground\";\n case \"off\":\n return \"text-muted-foreground\";\n default:\n return \"text-primary\";\n }\n}\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"ConnectionLoggingPolicy.js","sources":["../../src/components/ConnectionLoggingPolicy.tsx"],"sourcesContent":["import { useState } from \"react\";\nimport { cn } from \"../lib/utils\";\nimport { SegmentedControl } from \"./SegmentedControl\";\nimport { Select } from \"./select\";\nimport {\n CONNECTION_LOG_LEVELS,\n effectiveConnectionLogLevel,\n parseConnectionLoggingThreshold,\n visibleConnectionLogEvents,\n type ConnectionLogLevel,\n type ConnectionLoggingPolicyProps,\n type ConnectionLoggingThreshold,\n} from \"./ConnectionLoggingPolicy.model\";\n\nconst LEVEL_OPTIONS = CONNECTION_LOG_LEVELS.map((level) => ({\n value: level,\n label: level === \"off\" ? \"Off\" : level[0]?.toUpperCase() + level.slice(1),\n}));\nconst LEVEL_SEGMENTS = LEVEL_OPTIONS.map(({ value, label }) => ({\n id: value,\n label,\n}));\n\nconst THRESHOLD_PROPERTY = \"log.slowThreshold\";\ntype PreviewFormat = \"pretty\" | \"json\";\n\nexport function ConnectionLoggingPolicy({\n definition,\n value = {},\n onChange,\n readOnly = false,\n className,\n}: ConnectionLoggingPolicyProps) {\n const [previewLevel, setPreviewLevel] = useState<ConnectionLogLevel>(\"debug\");\n const [previewFormat, setPreviewFormat] = useState<PreviewFormat>(\"pretty\");\n const threshold = parseConnectionLoggingThreshold(\n value[THRESHOLD_PROPERTY] ?? definition.slowThreshold,\n );\n const visibleEvents = visibleConnectionLogEvents(\n definition,\n value,\n previewLevel,\n );\n\n const updateOverride = (\n property: string,\n next: string,\n defaultValue: string,\n ) => {\n const updated = { ...value };\n if (next === defaultValue) delete updated[property];\n else updated[property] = next;\n onChange(updated);\n };\n\n return (\n <section\n className={cn(\n \"space-y-density-4 rounded-lg border border-border bg-card p-density-4\",\n className,\n )}\n >\n <header className=\"flex flex-wrap items-start justify-between gap-density-3\">\n <div className=\"space-y-1\">\n <h3 className=\"text-sm font-semibold text-foreground\">\n Connection logging\n </h3>\n <p className=\"max-w-3xl text-xs leading-relaxed text-muted-foreground\">\n Errors win over slow operations, then the provider-specific record.\n Payloads are bounded and credentials are sanitized before logging.\n </p>\n </div>\n <span className=\"font-mono text-[11px] font-medium uppercase tracking-wide text-muted-foreground\">\n {definition.family}\n </span>\n </header>\n\n <div className=\"grid gap-density-4 xl:grid-cols-[minmax(0,1.2fr)_minmax(22rem,0.8fr)]\">\n <div className=\"space-y-density-3\">\n <ThresholdControl\n label={definition.thresholdLabel}\n threshold={threshold}\n disabled={readOnly}\n onChange={(next) =>\n updateOverride(\n THRESHOLD_PROPERTY,\n `${next.amount}${next.unit}`,\n definition.slowThreshold,\n )\n }\n />\n\n <div className=\"overflow-hidden rounded-md border border-border\">\n {definition.events.map((event) => {\n const level = effectiveConnectionLogLevel(event, value);\n return (\n <div\n key={event.event}\n className=\"grid gap-density-2 border-b border-border px-density-3 py-density-2 last:border-b-0 xl:grid-cols-[minmax(12rem,1fr)_auto] xl:items-center\"\n >\n <div className=\"min-w-0 space-y-1\">\n <div className=\"flex flex-wrap items-center gap-2\">\n <span className=\"text-sm font-medium text-foreground\">\n {event.label}\n </span>\n <span className=\"font-mono text-[10px] text-muted-foreground\">\n {event.property}\n </span>\n </div>\n <p className=\"text-xs text-muted-foreground\">{event.description}</p>\n <p className=\"text-[10px] text-muted-foreground/80\">\n Captures {event.captures.join(\", \")}\n </p>\n </div>\n <div className=\"flex flex-wrap items-center gap-density-2\">\n <SegmentedControl<ConnectionLogLevel>\n aria-label={`${event.label} level`}\n value={level}\n options={LEVEL_SEGMENTS.map((option) => ({\n ...option,\n disabled: readOnly,\n }))}\n onChange={(next) =>\n updateOverride(event.property, next, event.default)\n }\n size=\"sm\"\n wrap\n />\n <span className=\"text-[10px] text-muted-foreground\">\n Default {event.default}\n </span>\n </div>\n </div>\n );\n })}\n </div>\n </div>\n\n <aside className=\"min-w-0 space-y-density-3 rounded-md border border-border bg-background p-density-3\">\n <div className=\"flex flex-wrap items-end justify-between gap-density-2\">\n <div>\n <h4 className=\"text-sm font-semibold text-foreground\">\n What gets logged\n </h4>\n <p className=\"text-xs text-muted-foreground\">\n Cumulative records at the effective logger level.\n </p>\n </div>\n <div className=\"flex flex-wrap items-end gap-density-2\">\n <div className=\"space-y-1 text-xs font-medium text-muted-foreground\">\n Preview format\n <SegmentedControl<PreviewFormat>\n aria-label=\"Preview format\"\n value={previewFormat}\n size=\"sm\"\n options={[\n { id: \"pretty\", label: \"Pretty\" },\n { id: \"json\", label: \"JSON\" },\n ]}\n onChange={setPreviewFormat}\n />\n </div>\n <label className=\"w-36 space-y-1 text-xs font-medium text-muted-foreground\">\n Preview level\n <Select\n aria-label=\"Preview logger level\"\n value={previewLevel}\n options={LEVEL_OPTIONS}\n onChange={(event) =>\n setPreviewLevel(event.target.value as ConnectionLogLevel)\n }\n />\n </label>\n </div>\n </div>\n\n <div\n data-testid=\"connection-log-preview\"\n className=\"space-y-density-2\"\n >\n {visibleEvents.length === 0 ? (\n <div className=\"rounded-md border border-dashed border-border p-density-4 text-center text-xs text-muted-foreground\">\n No connection records are emitted at this level.\n </div>\n ) : (\n visibleEvents.map((event) => (\n <article\n key={event.event}\n data-testid=\"connection-log-preview-event\"\n className=\"overflow-hidden rounded-md border border-border\"\n >\n <div className=\"flex items-center justify-between gap-2 border-b border-border bg-muted/60 px-2.5 py-1.5\">\n <span className=\"text-xs font-medium text-foreground\">\n {event.label}\n </span>\n <span\n className={cn(\n \"font-mono text-[10px] font-semibold\",\n levelTone(effectiveConnectionLogLevel(event, value)),\n )}\n >\n {effectiveConnectionLogLevel(event, value)}\n </span>\n </div>\n <pre className=\"overflow-x-auto whitespace-pre-wrap break-words p-2.5 font-mono text-[11px] leading-relaxed text-foreground\">\n {previewFormat === \"pretty\"\n ? event.prettyExample\n : JSON.stringify(event.example, null, 2)}\n </pre>\n </article>\n ))\n )}\n </div>\n </aside>\n </div>\n </section>\n );\n}\n\nfunction ThresholdControl({\n label,\n threshold,\n disabled,\n onChange,\n}: {\n label: string;\n threshold: ConnectionLoggingThreshold;\n disabled: boolean;\n onChange: (next: ConnectionLoggingThreshold) => void;\n}) {\n return (\n <div className=\"flex flex-wrap items-end justify-between gap-density-3 rounded-md border border-border bg-muted/30 p-density-3\">\n <div>\n <div className=\"text-sm font-medium text-foreground\">{label}</div>\n <p className=\"text-xs text-muted-foreground\">\n A successful operation at or above this duration logs as slow.\n </p>\n </div>\n <div className=\"flex w-48 gap-2\">\n <input\n type=\"number\"\n min=\"0.001\"\n step=\"any\"\n aria-label=\"Slow threshold value\"\n value={threshold.amount}\n disabled={disabled}\n onChange={(event) => {\n if (Number(event.target.value) > 0)\n onChange({ ...threshold, amount: event.target.value });\n }}\n className=\"h-control-h min-w-0 flex-1 rounded-md border border-input bg-background px-control-px text-sm text-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring\"\n />\n <Select\n aria-label=\"Slow threshold unit\"\n value={threshold.unit}\n disabled={disabled}\n className=\"w-20\"\n options={[\n { value: \"ms\", label: \"ms\" },\n { value: \"s\", label: \"sec\" },\n { value: \"m\", label: \"min\" },\n { value: \"h\", label: \"hour\" },\n ]}\n onChange={(event) =>\n onChange({\n ...threshold,\n unit: event.target.value as ConnectionLoggingThreshold[\"unit\"],\n })\n }\n />\n </div>\n </div>\n );\n}\n\nfunction levelTone(level: ConnectionLogLevel) {\n switch (level) {\n case \"error\":\n return \"text-destructive\";\n case \"warn\":\n return \"text-warning-foreground\";\n case \"info\":\n return \"text-foreground\";\n case \"off\":\n return \"text-muted-foreground\";\n default:\n return \"text-primary\";\n }\n}\n"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"MultiSelect.cjs","sources":["../../src/components/MultiSelect.tsx"],"sourcesContent":["import { useMemo, useState, type ReactNode, type Ref } from \"react\";\nimport {\n autoUpdate,\n flip,\n FloatingFocusManager,\n FloatingPortal,\n offset,\n shift,\n useClick,\n useDismiss,\n useFloating,\n useInteractions,\n useRole,\n} from \"@floating-ui/react\";\nimport { Button } from \"./button\";\nimport { cn } from \"../lib/utils\";\nimport { Icon } from \"../data/Icon\";\nimport { UiChevronDown, UiChevronUp } from \"../icons\";\nimport { useEscapeLayer, useFloatingZIndex } from \"../overlay/modalStack\";\n\nexport type MultiSelectOption = {\n /** Stable option value written into the selected value array. */\n value: string;\n /** Visible option label in the menu and trigger summary. */\n label: ReactNode;\n /** Prevents selecting this option while still showing it in the menu. */\n disabled?: boolean;\n /** Optional browser tooltip for truncated or explanatory labels. */\n title?: string;\n};\n\nexport type MultiSelectProps = {\n /** Available options, rendered in the order provided. */\n options: MultiSelectOption[];\n /** Controlled selected option values. */\n value: string[];\n /** Called with the complete next value array after each toggle. */\n onChange: (next: string[]) => void;\n /** Trigger text when nothing is selected. Also labels the menu. */\n placeholder?: string;\n /** Accessible name for the trigger. Use when the field is labelled\n * elsewhere so the trigger doesn't have to borrow `placeholder` for its\n * name (which would force a synthesized placeholder). */\n ariaLabel?: string;\n /** Disables opening and changing selections. */\n disabled?: boolean;\n /** Classes applied to the root wrapper. */\n className?: string;\n /** Classes applied to the trigger button. */\n triggerClassName?: string;\n /** Classes applied to the popover menu. */\n menuClassName?: string;\n};\n\nexport function MultiSelect({\n options,\n value,\n onChange,\n placeholder = \"Select options\",\n ariaLabel,\n disabled,\n className,\n triggerClassName,\n menuClassName,\n}: MultiSelectProps) {\n const [open, setOpen] = useState(false);\n\n // Portaled (floating-ui) so the menu escapes `overflow` clipping from\n // scroll-container ancestors, matching Combobox/DropdownMenu.\n const floatingZ = useFloatingZIndex();\n const { refs, floatingStyles, context } = useFloating({\n open,\n onOpenChange: setOpen,\n placement: \"bottom-start\",\n whileElementsMounted: autoUpdate,\n middleware: [offset(6), flip({ padding: 8 }), shift({ padding: 8 })],\n });\n const { getReferenceProps, getFloatingProps } = useInteractions([\n useClick(context),\n useDismiss(context, { escapeKey: false }),\n useRole(context, { role: \"menu\" }),\n ]);\n useEscapeLayer(open, () => {\n setOpen(false);\n if (refs.domReference.current instanceof HTMLElement) refs.domReference.current.focus();\n });\n\n const selected = useMemo(() => {\n const selectedOptions = options.filter((option) => value.includes(option.value));\n const labels = selectedOptions\n .map((option) => option.label)\n .filter((label): label is string => typeof label === \"string\");\n\n if (selectedOptions.length === 0) return placeholder;\n if (labels.length === 0) return `${selectedOptions.length} selected`;\n if (labels.length <= 2) return labels.join(\", \");\n return `${labels.length} selected`;\n }, [options, placeholder, value]);\n\n function toggleOption(nextValue: string) {\n if (value.includes(nextValue)) {\n onChange(value.filter((current) => current !== nextValue));\n return;\n }\n onChange([...value, nextValue]);\n }\n\n // `min-w-0` here, and a shrinkable trigger below, let the summary ellipsize\n // inside a width-capped flex parent (a FilterBar chip) rather than overflow\n // onto its neighbour.\n return (\n <div className={cn(\"inline-flex min-w-0\", className)}>\n <Button\n ref={refs.setReference as Ref<HTMLButtonElement>}\n type=\"button\"\n variant=\"outline\"\n disabled={disabled}\n aria-label={ariaLabel ?? `${placeholder} filter`}\n className={cn(\n \"w-fit max-w-[15rem] min-w-0 justify-between gap-3 text-left font-normal\",\n triggerClassName,\n // Empty means the trigger is showing its placeholder, so it reads at\n // placeholder weight rather than at helper-text weight.\n value.length === 0 && \"text-placeholder\",\n )}\n {...getReferenceProps()}\n >\n <span className=\"truncate\">{selected}</span>\n <Icon icon={open ? UiChevronUp : UiChevronDown} className=\"shrink-0 text-muted-foreground\" />\n </Button>\n {open && (\n <FloatingPortal>\n <FloatingFocusManager context={context} modal={false}>\n <div\n ref={refs.setFloating}\n role=\"menu\"\n aria-label={placeholder}\n style={{ ...floatingStyles, zIndex: floatingZ }}\n className={cn(\n \"min-w-[14rem] max-w-[20rem] rounded-md border border-border bg-popover p-1 text-popover-foreground shadow-lg shadow-black/5\",\n menuClassName,\n )}\n {...getFloatingProps()}\n >\n <div className=\"mb-1 flex items-center justify-between gap-2 px-2 py-1 text-[10px] font-medium uppercase tracking-wide text-muted-foreground\">\n <span>{placeholder}</span>\n <button\n type=\"button\"\n className=\"text-[10px] text-primary disabled:text-muted-foreground\"\n onClick={() => onChange([])}\n disabled={value.length === 0}\n >\n Clear all\n </button>\n </div>\n <div className=\"max-h-64 overflow-auto\">\n {options.map((option) => {\n const checked = value.includes(option.value);\n return (\n <label\n key={option.value}\n className={cn(\n \"flex cursor-pointer items-center gap-2 rounded-sm px-2 py-1.5 text-sm hover:bg-accent\",\n option.disabled && \"cursor-not-allowed opacity-50\",\n )}\n >\n <input\n type=\"checkbox\"\n role=\"menuitemcheckbox\"\n className=\"size-4 rounded border border-input\"\n checked={checked}\n disabled={option.disabled}\n onChange={() => toggleOption(option.value)}\n />\n <span className=\"min-w-0 truncate\">{option.label}</span>\n </label>\n );\n })}\n </div>\n </div>\n </FloatingFocusManager>\n </FloatingPortal>\n )}\n </div>\n );\n}\n"],"names":["useState","useFloatingZIndex","useFloating","autoUpdate","offset","flip","shift","useInteractions","useClick","useDismiss","useRole","useEscapeLayer","useMemo","cn","jsxs","Button","jsx","Icon","UiChevronUp","UiChevronDown","FloatingPortal","FloatingFocusManager"],"mappings":"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"}
1
+ {"version":3,"file":"MultiSelect.cjs","sources":["../../src/components/MultiSelect.tsx"],"sourcesContent":["import { useMemo, useState, type ReactNode, type Ref } from \"react\";\nimport {\n autoUpdate,\n flip,\n FloatingFocusManager,\n FloatingPortal,\n offset,\n shift,\n useClick,\n useDismiss,\n useFloating,\n useInteractions,\n useRole,\n} from \"@floating-ui/react\";\nimport { Button } from \"./button\";\nimport { cn } from \"../lib/utils\";\nimport { Icon, type LabelIconSpec } from \"../data/Icon\";\nimport { UiChevronDown, UiChevronUp } from \"../icons\";\nimport { useEscapeLayer, useFloatingZIndex } from \"../overlay/modalStack\";\n\nexport type MultiSelectOption = {\n /** Stable option value written into the selected value array. */\n value: string;\n /** Visible option label in the menu and trigger summary. */\n label: ReactNode;\n /** Secondary text rendered below the option label. */\n description?: string;\n /** Optional compact label used after the option is selected. */\n selectedLabel?: string;\n /** Leading glyph rendered with the option label. */\n icon?: LabelIconSpec;\n /** Prevents selecting this option while still showing it in the menu. */\n disabled?: boolean;\n /** Optional browser tooltip for truncated or explanatory labels. */\n title?: string;\n};\n\nexport type MultiSelectProps = {\n /** Available options, rendered in the order provided. */\n options: MultiSelectOption[];\n /** Controlled selected option values. */\n value: string[];\n /** Called with the complete next value array after each toggle. */\n onChange: (next: string[]) => void;\n /** Trigger text when nothing is selected. Also labels the menu. */\n placeholder?: string;\n /** Accessible name for the trigger. Use when the field is labelled\n * elsewhere so the trigger doesn't have to borrow `placeholder` for its\n * name (which would force a synthesized placeholder). */\n ariaLabel?: string;\n /** Disables opening and changing selections. */\n disabled?: boolean;\n /** Classes applied to the root wrapper. */\n className?: string;\n /** Classes applied to the trigger button. */\n triggerClassName?: string;\n /** Classes applied to the popover menu. */\n menuClassName?: string;\n};\n\nexport function MultiSelect({\n options,\n value,\n onChange,\n placeholder = \"Select options\",\n ariaLabel,\n disabled,\n className,\n triggerClassName,\n menuClassName,\n}: MultiSelectProps) {\n const [open, setOpen] = useState(false);\n\n // Portaled (floating-ui) so the menu escapes `overflow` clipping from\n // scroll-container ancestors, matching Combobox/DropdownMenu.\n const floatingZ = useFloatingZIndex();\n const { refs, floatingStyles, context } = useFloating({\n open,\n onOpenChange: setOpen,\n placement: \"bottom-start\",\n whileElementsMounted: autoUpdate,\n middleware: [offset(6), flip({ padding: 8 }), shift({ padding: 8 })],\n });\n const { getReferenceProps, getFloatingProps } = useInteractions([\n useClick(context),\n useDismiss(context, { escapeKey: false }),\n useRole(context, { role: \"menu\" }),\n ]);\n useEscapeLayer(open, () => {\n setOpen(false);\n if (refs.domReference.current instanceof HTMLElement) refs.domReference.current.focus();\n });\n\n const selected = useMemo(() => {\n const selectedOptions = options.filter((option) => value.includes(option.value));\n const labels = selectedOptions\n .map((option) => option.label)\n .filter((label): label is string => typeof label === \"string\");\n\n if (selectedOptions.length === 0) return placeholder;\n if (labels.length === 0) return `${selectedOptions.length} selected`;\n if (labels.length <= 2) return labels.join(\", \");\n return `${labels.length} selected`;\n }, [options, placeholder, value]);\n\n function toggleOption(nextValue: string) {\n if (value.includes(nextValue)) {\n onChange(value.filter((current) => current !== nextValue));\n return;\n }\n onChange([...value, nextValue]);\n }\n\n // `min-w-0` here, and a shrinkable trigger below, let the summary ellipsize\n // inside a width-capped flex parent (a FilterBar chip) rather than overflow\n // onto its neighbour.\n return (\n <div className={cn(\"inline-flex min-w-0\", className)}>\n <Button\n ref={refs.setReference as Ref<HTMLButtonElement>}\n type=\"button\"\n variant=\"outline\"\n disabled={disabled}\n aria-label={ariaLabel ?? `${placeholder} filter`}\n className={cn(\n \"w-fit max-w-[15rem] min-w-0 justify-between gap-3 text-left font-normal\",\n triggerClassName,\n // Empty means the trigger is showing its placeholder, so it reads at\n // placeholder weight rather than at helper-text weight.\n value.length === 0 && \"text-placeholder\",\n )}\n {...getReferenceProps()}\n >\n <span className=\"truncate\">{selected}</span>\n <Icon icon={open ? UiChevronUp : UiChevronDown} className=\"shrink-0 text-muted-foreground\" />\n </Button>\n {open && (\n <FloatingPortal>\n <FloatingFocusManager context={context} modal={false}>\n <div\n ref={refs.setFloating}\n role=\"menu\"\n aria-label={placeholder}\n style={{ ...floatingStyles, zIndex: floatingZ }}\n className={cn(\n \"min-w-[14rem] max-w-[20rem] rounded-md border border-border bg-popover p-1 text-popover-foreground shadow-lg shadow-black/5\",\n menuClassName,\n )}\n {...getFloatingProps()}\n >\n <div className=\"mb-1 flex items-center justify-between gap-2 px-2 py-1 text-[10px] font-medium uppercase tracking-wide text-muted-foreground\">\n <span>{placeholder}</span>\n <button\n type=\"button\"\n className=\"text-[10px] text-primary disabled:text-muted-foreground\"\n onClick={() => onChange([])}\n disabled={value.length === 0}\n >\n Clear all\n </button>\n </div>\n <div className=\"max-h-64 overflow-auto\">\n {options.map((option) => {\n const checked = value.includes(option.value);\n return (\n <label\n key={option.value}\n className={cn(\n \"flex cursor-pointer items-center gap-2 rounded-sm px-2 py-1.5 text-sm hover:bg-accent\",\n option.disabled && \"cursor-not-allowed opacity-50\",\n )}\n >\n <input\n type=\"checkbox\"\n role=\"menuitemcheckbox\"\n className=\"size-4 rounded border border-input\"\n checked={checked}\n disabled={option.disabled}\n onChange={() => toggleOption(option.value)}\n />\n <span className=\"min-w-0 truncate\">{option.label}</span>\n </label>\n );\n })}\n </div>\n </div>\n </FloatingFocusManager>\n </FloatingPortal>\n )}\n </div>\n );\n}\n"],"names":["useState","useFloatingZIndex","useFloating","autoUpdate","offset","flip","shift","useInteractions","useClick","useDismiss","useRole","useEscapeLayer","useMemo","cn","jsxs","Button","jsx","Icon","UiChevronUp","UiChevronDown","FloatingPortal","FloatingFocusManager"],"mappings":"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"}