nudge-ui 0.2.2 → 0.2.4

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 (244) hide show
  1. package/README.md +164 -46
  2. package/dist/client.mjs +260 -61
  3. package/dist/css/value-semantics/colorSemantics.d.ts +4 -0
  4. package/dist/css/value-semantics/colorSemantics.js +17 -0
  5. package/dist/hosts/astro/astroRuntimeConfig.js +1 -0
  6. package/dist/hosts/astro/clientTransport.js +38 -32
  7. package/dist/hosts/astro/integration.js +5 -1
  8. package/dist/hosts/astro/markdownIdentity.d.ts +28 -0
  9. package/dist/hosts/astro/markdownIdentity.js +81 -0
  10. package/dist/hosts/next/manifest.js +1 -1
  11. package/dist/hosts/next/sidecar.js +5 -1
  12. package/dist/hosts/static/manifest.js +1 -1
  13. package/dist/hosts/static/server.js +3 -0
  14. package/dist/hosts/vite/vite.d.ts +3 -0
  15. package/dist/hosts/vite/vite.js +24 -4
  16. package/dist/inspector/agent/McpConnectionDialog.js +13 -19
  17. package/dist/inspector/agent/activity.d.ts +18 -0
  18. package/dist/inspector/agent/activity.js +70 -0
  19. package/dist/inspector/agent/client.d.ts +2 -0
  20. package/dist/inspector/agent/client.js +29 -1
  21. package/dist/inspector/agent/connectionStatus.js +1 -1
  22. package/dist/inspector/agent/httpTransport.js +9 -2
  23. package/dist/inspector/agent/protocol.d.ts +6 -3
  24. package/dist/inspector/agent/protocol.js +1 -1
  25. package/dist/inspector/agent/verification.d.ts +15 -7
  26. package/dist/inspector/agent/verification.js +113 -41
  27. package/dist/inspector/canvas/AgentActivityOverlay.d.ts +13 -0
  28. package/dist/inspector/canvas/AgentActivityOverlay.js +111 -0
  29. package/dist/inspector/canvas/CanvasCard.d.ts +9 -2
  30. package/dist/inspector/canvas/CanvasCard.js +135 -38
  31. package/dist/inspector/canvas/CanvasElementOverlay.js +166 -16
  32. package/dist/inspector/canvas/CanvasToolIcons.d.ts +10 -0
  33. package/dist/inspector/canvas/CanvasToolIcons.js +20 -0
  34. package/dist/inspector/canvas/CanvasToolbar.js +8 -4
  35. package/dist/inspector/canvas/CanvasWorkspace.js +270 -122
  36. package/dist/inspector/canvas/StaleChangeIndicator.js +3 -13
  37. package/dist/inspector/canvas/agentPresentation.d.ts +8 -8
  38. package/dist/inspector/canvas/agentPresentation.js +64 -52
  39. package/dist/inspector/canvas/canvasGestures.d.ts +1 -1
  40. package/dist/inspector/canvas/canvasGestures.js +1 -1
  41. package/dist/inspector/canvas/canvasStore.d.ts +46 -82
  42. package/dist/inspector/canvas/canvasStore.js +251 -284
  43. package/dist/inspector/canvas/frameContent.d.ts +21 -0
  44. package/dist/inspector/canvas/frameContent.js +44 -0
  45. package/dist/inspector/canvas/frameProtocol.d.ts +21 -4
  46. package/dist/inspector/canvas/frameProtocol.js +3 -3
  47. package/dist/inspector/canvas/frameScrollbarStyles.d.ts +3 -0
  48. package/dist/inspector/canvas/frameScrollbarStyles.js +21 -0
  49. package/dist/inspector/canvas/keyboardShortcuts.d.ts +3 -1
  50. package/dist/inspector/canvas/keyboardShortcuts.js +4 -4
  51. package/dist/inspector/canvas/layout.d.ts +52 -0
  52. package/dist/inspector/canvas/layout.js +106 -0
  53. package/dist/inspector/canvas/projection.d.ts +15 -5
  54. package/dist/inspector/canvas/projection.js +69 -13
  55. package/dist/inspector/canvas/rendererBootstrap.js +32 -4
  56. package/dist/inspector/canvas/rendererElementSelector.js +47 -6
  57. package/dist/inspector/canvas/rendererStylesheet.js +2 -2
  58. package/dist/inspector/canvas/resizeHandleScale.js +1 -1
  59. package/dist/inspector/canvas/sessionStore.d.ts +11 -26
  60. package/dist/inspector/canvas/sessionStore.js +43 -183
  61. package/dist/inspector/canvas/staleChangeDetector.js +9 -3
  62. package/dist/inspector/canvas/useCanvasLayoutAnimation.d.ts +5 -0
  63. package/dist/inspector/canvas/useCanvasLayoutAnimation.js +107 -0
  64. package/dist/inspector/canvas/viewStore.d.ts +38 -0
  65. package/dist/inspector/canvas/viewStore.js +104 -0
  66. package/dist/inspector/canvas/wheelPan.d.ts +8 -0
  67. package/dist/inspector/canvas/wheelPan.js +8 -0
  68. package/dist/inspector/changes/changesLog.d.ts +9 -6
  69. package/dist/inspector/changes/changesLog.js +48 -32
  70. package/dist/inspector/changes/codecs.d.ts +1 -0
  71. package/dist/inspector/changes/codecs.js +10 -1
  72. package/dist/inspector/changes/draftChanges.d.ts +58 -0
  73. package/dist/inspector/changes/draftChanges.js +304 -0
  74. package/dist/inspector/changes/editModel.d.ts +10 -0
  75. package/dist/inspector/changes/editModel.js +9 -2
  76. package/dist/inspector/changes/previewDiagnostics.d.ts +4 -2
  77. package/dist/inspector/changes/previewDiagnostics.js +11 -25
  78. package/dist/inspector/changes/types.d.ts +7 -0
  79. package/dist/inspector/clientManifest.d.ts +1 -1
  80. package/dist/inspector/comments/CommentsOverlay.d.ts +2 -0
  81. package/dist/inspector/comments/CommentsOverlay.js +250 -0
  82. package/dist/inspector/comments/element.d.ts +6 -0
  83. package/dist/inspector/comments/element.js +54 -0
  84. package/dist/inspector/comments/store.d.ts +29 -0
  85. package/dist/inspector/comments/store.js +121 -0
  86. package/dist/inspector/comments/verification.d.ts +5 -0
  87. package/dist/inspector/comments/verification.js +52 -0
  88. package/dist/inspector/componentSemantics/adapterRegistry.d.ts +6 -1
  89. package/dist/inspector/componentSemantics/adapterRegistry.js +23 -1
  90. package/dist/inspector/componentSemantics/reactRuntime.d.ts +2 -1
  91. package/dist/inspector/componentSemantics/reactRuntime.js +38 -0
  92. package/dist/inspector/componentSemantics/runtimeBridge.d.ts +4 -2
  93. package/dist/inspector/componentSemantics/runtimeBridge.js +17 -0
  94. package/dist/inspector/componentSemantics/types.d.ts +11 -0
  95. package/dist/inspector/drafts/model.d.ts +35 -0
  96. package/dist/inspector/drafts/model.js +45 -0
  97. package/dist/inspector/drafts/store.d.ts +28 -0
  98. package/dist/inspector/drafts/store.js +231 -0
  99. package/dist/inspector/index.js +20 -27
  100. package/dist/inspector/inline-text/inlineTextEditor.js +7 -0
  101. package/dist/inspector/inspection/useBrowserCssInspection.js +15 -1
  102. package/dist/inspector/iterations/capture.d.ts +2 -0
  103. package/dist/inspector/iterations/capture.js +174 -0
  104. package/dist/inspector/iterations/client.d.ts +7 -0
  105. package/dist/inspector/iterations/client.js +52 -0
  106. package/dist/inspector/iterations/coordinator.d.ts +15 -0
  107. package/dist/inspector/iterations/coordinator.js +130 -0
  108. package/dist/inspector/iterations/prompt.d.ts +3 -0
  109. package/dist/inspector/iterations/prompt.js +26 -0
  110. package/dist/inspector/overlay/DomNavigator.js +21 -15
  111. package/dist/inspector/overlay/interactionStyles.js +3 -1
  112. package/dist/inspector/overlay/spacingGestures.d.ts +13 -1
  113. package/dist/inspector/overlay/spacingGestures.js +82 -5
  114. package/dist/inspector/projection/{workspaceProjection.d.ts → draftProjection.d.ts} +6 -6
  115. package/dist/inspector/projection/{workspaceProjection.js → draftProjection.js} +4 -4
  116. package/dist/inspector/projection/renderedInstance.d.ts +17 -3
  117. package/dist/inspector/projection/renderedInstance.js +62 -11
  118. package/dist/inspector/projection/structuralProjection.d.ts +2 -1
  119. package/dist/inspector/projection/structuralProjection.js +21 -17
  120. package/dist/inspector/projection/textProjection.d.ts +2 -1
  121. package/dist/inspector/projection/textProjection.js +64 -15
  122. package/dist/inspector/prompt/PromptSettingsDialog.js +1 -5
  123. package/dist/inspector/prompt/clipboardHandoff.d.ts +15 -18
  124. package/dist/inspector/prompt/clipboardHandoff.js +97 -143
  125. package/dist/inspector/prompt/generatePrompt.d.ts +4 -1
  126. package/dist/inspector/prompt/generatePrompt.js +22 -17
  127. package/dist/inspector/runtime/runtimeConfig.d.ts +9 -0
  128. package/dist/inspector/runtime/runtimeConfig.js +24 -0
  129. package/dist/inspector/selection/sourceSite.d.ts +12 -0
  130. package/dist/inspector/selection/sourceSite.js +28 -0
  131. package/dist/inspector/settings/SettingsDialog.js +21 -8
  132. package/dist/inspector/shell/AgentStatusButton.d.ts +11 -0
  133. package/dist/inspector/shell/AgentStatusButton.js +36 -0
  134. package/dist/inspector/shell/AppShell.js +4 -2
  135. package/dist/inspector/shell/ChangesLog.js +46 -26
  136. package/dist/inspector/shell/CopyPromptButton.js +184 -93
  137. package/dist/inspector/shell/EmptyState.js +9 -8
  138. package/dist/inspector/shell/InspectorShell.js +13 -21
  139. package/dist/inspector/shell/PeekOriginalButton.js +24 -23
  140. package/dist/inspector/shell/originalPreview.js +5 -5
  141. package/dist/inspector/shell/shortcuts.d.ts +3 -0
  142. package/dist/inspector/shell/shortcuts.js +11 -0
  143. package/dist/inspector/sketch/SketchEditor.js +14 -14
  144. package/dist/inspector/sketch/SketchEntryButton.js +1 -1
  145. package/dist/inspector/sketch/SketchFrameOverlay.d.ts +3 -1
  146. package/dist/inspector/sketch/SketchFrameOverlay.js +11 -8
  147. package/dist/inspector/sketch/SketchLayersPanel.js +13 -5
  148. package/dist/inspector/sketch/SketchOverlay.js +7 -7
  149. package/dist/inspector/sketch/SketchWorkspace.js +18 -12
  150. package/dist/inspector/sketch/interaction.d.ts +1 -0
  151. package/dist/inspector/sketch/interaction.js +8 -4
  152. package/dist/inspector/sketch/model.d.ts +5 -0
  153. package/dist/inspector/sketch/model.js +6 -2
  154. package/dist/inspector/sketch/raster.d.ts +1 -2
  155. package/dist/inspector/sketch/raster.js +68 -4
  156. package/dist/inspector/styleEditors/BackgroundEditor.d.ts +4 -0
  157. package/dist/inspector/styleEditors/BackgroundEditor.js +195 -0
  158. package/dist/inspector/styleEditors/BorderEditor.js +49 -78
  159. package/dist/inspector/styleEditors/BorderRadiusEditor.js +6 -1
  160. package/dist/inspector/styleEditors/BoxShadowEditor.d.ts +1 -2
  161. package/dist/inspector/styleEditors/BoxShadowEditor.js +132 -4
  162. package/dist/inspector/styleEditors/ColorPicker.d.ts +5 -1
  163. package/dist/inspector/styleEditors/ColorPicker.js +10 -4
  164. package/dist/inspector/styleEditors/GapField.js +3 -5
  165. package/dist/inspector/styleEditors/GridChildSection.d.ts +1 -1
  166. package/dist/inspector/styleEditors/GridChildSection.js +18 -9
  167. package/dist/inspector/styleEditors/GridPicker.d.ts +1 -1
  168. package/dist/inspector/styleEditors/GridPicker.js +8 -2
  169. package/dist/inspector/styleEditors/GridSection.js +1 -1
  170. package/dist/inspector/styleEditors/GridValueField.js +19 -14
  171. package/dist/inspector/styleEditors/ImageBackgroundEditor.d.ts +18 -0
  172. package/dist/inspector/styleEditors/ImageBackgroundEditor.js +118 -0
  173. package/dist/inspector/styleEditors/LayoutBlockedIndicator.d.ts +2 -2
  174. package/dist/inspector/styleEditors/LayoutBlockedIndicator.js +3 -3
  175. package/dist/inspector/styleEditors/LayoutComboField.js +6 -4
  176. package/dist/inspector/styleEditors/LayoutDropdown.js +6 -3
  177. package/dist/inspector/styleEditors/LayoutSection.js +32 -11
  178. package/dist/inspector/styleEditors/SpacingBox.js +7 -5
  179. package/dist/inspector/styleEditors/Typography.js +11 -3
  180. package/dist/inspector/styleEditors/backgroundLayers.d.ts +24 -0
  181. package/dist/inspector/styleEditors/backgroundLayers.js +51 -0
  182. package/dist/inspector/styleEditors/gradientValue.d.ts +17 -0
  183. package/dist/inspector/styleEditors/gradientValue.js +114 -0
  184. package/dist/inspector/styleEditors/inlineAuthored.d.ts +10 -0
  185. package/dist/inspector/styleEditors/inlineAuthored.js +114 -0
  186. package/dist/inspector/styleEditors/layoutValue.d.ts +0 -8
  187. package/dist/inspector/styleEditors/layoutValue.js +0 -42
  188. package/dist/inspector/styleEditors/nudgeValue.d.ts +2 -2
  189. package/dist/inspector/styleEditors/nudgeValue.js +36 -8
  190. package/dist/inspector/tokens/TokenField.d.ts +7 -0
  191. package/dist/inspector/tokens/TokenField.js +35 -25
  192. package/dist/inspector/tokens/TokenLabel.js +5 -14
  193. package/dist/inspector/tokens/editActions.d.ts +1 -1
  194. package/dist/inspector/tokens/editActions.js +7 -1
  195. package/dist/inspector/ui/AtRuleContext.js +4 -6
  196. package/dist/inspector/ui/Button.d.ts +6 -2
  197. package/dist/inspector/ui/Button.js +4 -3
  198. package/dist/inspector/ui/ControlSurface.d.ts +2 -2
  199. package/dist/inspector/ui/ControlSurface.js +4 -3
  200. package/dist/inspector/ui/InlineStyleWarning.d.ts +11 -0
  201. package/dist/inspector/ui/InlineStyleWarning.js +13 -0
  202. package/dist/inspector/ui/InspectorPopover.d.ts +2 -1
  203. package/dist/inspector/ui/InspectorPopover.js +4 -5
  204. package/dist/inspector/ui/PopoverListbox.d.ts +2 -1
  205. package/dist/inspector/ui/PopoverListbox.js +8 -7
  206. package/dist/inspector/ui/SegmentedControl.d.ts +2 -1
  207. package/dist/inspector/ui/SegmentedControl.js +2 -2
  208. package/dist/inspector/ui/Select.d.ts +6 -1
  209. package/dist/inspector/ui/Select.js +7 -11
  210. package/dist/inspector/ui/SideValuesField.js +1 -1
  211. package/dist/inspector/ui/Tooltip.d.ts +26 -0
  212. package/dist/inspector/ui/Tooltip.js +32 -0
  213. package/dist/inspector/ui/classNames.d.ts +2 -0
  214. package/dist/inspector/ui/classNames.js +4 -0
  215. package/dist/inspector/ui/customCursors.d.ts +23 -0
  216. package/dist/inspector/ui/customCursors.js +122 -0
  217. package/dist/inspector/ui/dragCursor.d.ts +0 -2
  218. package/dist/inspector/ui/dragCursor.js +2 -10
  219. package/dist/inspector/ui/portalContainer.d.ts +2 -0
  220. package/dist/inspector/ui/portalContainer.js +6 -0
  221. package/dist/inspector/ui/styles.js +29 -21
  222. package/dist/inspector/workspace/commands.d.ts +9 -0
  223. package/dist/inspector/workspace/commands.js +82 -0
  224. package/dist/inspector/workspace/controller.d.ts +4 -0
  225. package/dist/inspector/workspace/controller.js +66 -0
  226. package/dist/inspector/workspace/handoff.d.ts +42 -0
  227. package/dist/inspector/workspace/handoff.js +115 -0
  228. package/dist/inspector/workspace/sentItems.d.ts +19 -0
  229. package/dist/inspector/workspace/sentItems.js +51 -0
  230. package/dist/inspector/workspace/timeline.d.ts +30 -0
  231. package/dist/inspector/workspace/timeline.js +108 -0
  232. package/dist/internal/agent-protocol.d.ts +19 -2
  233. package/dist/internal/agent-protocol.js +13 -0
  234. package/dist/nudge-ui.mjs +558 -311
  235. package/dist/project/artifacts.d.ts +13 -0
  236. package/dist/project/artifacts.js +253 -0
  237. package/dist/transport/artifacts.d.ts +8 -0
  238. package/dist/transport/artifacts.js +9 -0
  239. package/dist/transport/editor.js +3 -1
  240. package/dist/transport/routes.d.ts +2 -0
  241. package/dist/transport/routes.js +2 -0
  242. package/package.json +7 -3
  243. package/dist/inspector/changes/workspaceChanges.d.ts +0 -47
  244. package/dist/inspector/changes/workspaceChanges.js +0 -265
@@ -12,10 +12,14 @@ import { PopoverListbox } from "../ui/PopoverListbox.js";
12
12
  import { ColorSwatch } from "../ui/ColorSwatch.js";
13
13
  import { getStateStyleValue } from "../shell/stateValue.js";
14
14
  import { AtRuleIndicator, useFieldAtRules } from "../ui/AtRuleContext.js";
15
+ import { Tooltip } from "../ui/Tooltip.js";
16
+ import { cx } from "../ui/classNames.js";
15
17
  import { TokenChip } from "./TokenChip.js";
16
18
  import { startDragPointerLock } from "./dragPointerLock.js";
17
- import { createChangeHistoryGroup } from "../changes/workspaceChanges.js";
19
+ import { createChangeHistoryGroup } from "../changes/draftChanges.js";
18
20
  import { isMultiTarget } from "../selection/editTarget.js";
21
+ import { inlineBlockedBy } from "../styleEditors/inlineAuthored.js";
22
+ import { InlineStyleWarning } from "../ui/InlineStyleWarning.js";
19
23
  const NON_COLOR_FACTS = { hasEmbeddedAlpha: false, isExpression: false, opacityEditable: false };
20
24
  function colorFacts(value) {
21
25
  return selectTokens({
@@ -100,11 +104,13 @@ function primaryFontFamily(value) {
100
104
  return value.trim();
101
105
  }
102
106
  function rgbToHex(value) {
103
- const match = value.match(/^rgba?\(\s*(\d+(?:\.\d+)?)\D+(\d+(?:\.\d+)?)\D+(\d+(?:\.\d+)?)/i);
104
- if (!match)
107
+ const rgb = value.match(/^rgba?\(\s*(\d+(?:\.\d+)?)\D+(\d+(?:\.\d+)?)\D+(\d+(?:\.\d+)?)/i);
108
+ const srgb = rgb ? null : value.match(/^color\(\s*srgb\s+([\d.e+-]+)\s+([\d.e+-]+)\s+([\d.e+-]+)/i);
109
+ const channels = rgb ? [rgb[1], rgb[2], rgb[3]].map(Number) : srgb ? [srgb[1], srgb[2], srgb[3]].map((part) => Number(part) * 255) : null;
110
+ if (!channels || channels.some((channel) => !Number.isFinite(channel)))
105
111
  return null;
106
- return `#${[match[1], match[2], match[3]]
107
- .map((part) => Math.max(0, Math.min(255, Math.round(Number(part)))).toString(16).padStart(2, "0"))
112
+ return `#${channels
113
+ .map((channel) => Math.max(0, Math.min(255, Math.round(channel))).toString(16).padStart(2, "0"))
108
114
  .join("")}`;
109
115
  }
110
116
  export function colorValueToHex(value) {
@@ -155,7 +161,8 @@ function NativeColorSwatch({ value, onChange, disabled, }) {
155
161
  return (_jsxs("label", { className: "token-color-control", "data-resolved": hasRenderableColor ? "true" : "false", children: [_jsx(ColorSwatch, { color: cssColor ?? "transparent", "data-test": "token-color-swatch" }), _jsx("input", { className: "token-color-control__input", "data-test": "token-color-input", type: "color", value: hex, disabled: disabled, "aria-label": "Choose color", onChange: (event) => onChange(event.target.value) })] }));
156
162
  }
157
163
  export function TokenValueField(props) {
158
- const { property, domElement, semanticSlot, committedValue, resolvedValue = committedValue, activeTokenName: controlledTokenName = null, entries, suggestions = [], inputDataTest = "raw-input", allowedTokenNames, isColor = false, disabled = false, mixed = false, formatRawValue = (value) => value.trim(), onCommitRaw, onSelectToken, onUnlink, attributionTokens = [], leading, trailing, className, label, opacity, color, onCommitOpacity, atRules, chipVariant = "default", } = props;
164
+ const { property, nudgeProperty = property, domElement, semanticSlot, committedValue, resolvedValue = committedValue, activeTokenName: controlledTokenName = null, entries, suggestions = [], inputDataTest = "raw-input", allowedTokenNames, isColor = false, disabled = false, mixed = false, formatRawValue = (value) => value.trim(), onCommitRaw, onSelectToken, onUnlink, attributionTokens = [], leading, trailing, className, label, opacity, color, onCommitOpacity, atRules, chipVariant = "default", blockedBy = null, inlineWarningDataTest, inlineWarningTooltipDataTest, } = props;
165
+ const fieldDisabled = disabled || blockedBy !== null;
159
166
  const inheritedAtRules = useFieldAtRules(property);
160
167
  const fieldAtRules = atRules ?? inheritedAtRules;
161
168
  const controlledToken = controlledTokenName ? entries.find((entry) => entry.name === controlledTokenName) : null;
@@ -243,6 +250,8 @@ export function TokenValueField(props) {
243
250
  handleTokenSelect(chosen);
244
251
  }
245
252
  function commitRawValue(value = rawValue) {
253
+ if (fieldDisabled)
254
+ return;
246
255
  if (mixed && value.trim().toLowerCase() === "mixed")
247
256
  return;
248
257
  const formatted = formatRawValue(value);
@@ -286,7 +295,7 @@ export function TokenValueField(props) {
286
295
  if (direction && !event.altKey && !event.ctrlKey && !event.metaKey) {
287
296
  const next = property === "opacity"
288
297
  ? nudgeOpacityValue(rawValue, direction, event.shiftKey)
289
- : nudgeCssValue(property, rawValue, direction, event.shiftKey);
298
+ : nudgeCssValue(nudgeProperty, rawValue, direction, event.shiftKey);
290
299
  if (next) {
291
300
  event.preventDefault();
292
301
  event.stopPropagation();
@@ -336,9 +345,9 @@ export function TokenValueField(props) {
336
345
  function handleDragNudgePointerDown(event) {
337
346
  if (event.button !== 0)
338
347
  return;
339
- if (disabled || !supportsDragNudge(property))
348
+ if (fieldDisabled || !supportsDragNudge(nudgeProperty))
340
349
  return;
341
- if (!canNudgeCssValueByDrag(property, rawValue))
350
+ if (!canNudgeCssValueByDrag(nudgeProperty, rawValue))
342
351
  return;
343
352
  stopDragNudge();
344
353
  const handle = event.currentTarget;
@@ -386,7 +395,7 @@ export function TokenValueField(props) {
386
395
  drag.shiftSnapPending = event.shiftKey;
387
396
  }
388
397
  drag.deltaX += movementX;
389
- const next = nudgeCssValueByDrag(property, drag.startValue, drag.deltaX, drag.shiftActive, drag.shiftActive && drag.shiftSnapPending);
398
+ const next = nudgeCssValueByDrag(nudgeProperty, drag.startValue, drag.deltaX, drag.shiftActive, drag.shiftActive && drag.shiftSnapPending);
390
399
  if (next === null || next === drag.lastValue)
391
400
  return;
392
401
  drag.lastValue = next;
@@ -409,15 +418,15 @@ export function TokenValueField(props) {
409
418
  function renderLeading() {
410
419
  if (!leading)
411
420
  return null;
412
- const canDrag = !disabled
413
- && supportsDragNudge(property)
414
- && canNudgeCssValueByDrag(property, rawValue);
421
+ const canDrag = !fieldDisabled
422
+ && supportsDragNudge(nudgeProperty)
423
+ && canNudgeCssValueByDrag(nudgeProperty, rawValue);
415
424
  if (!canDrag)
416
425
  return _jsx("span", { className: "token-field__leading", children: leading });
417
- return (_jsx("span", { className: "token-field__leading token-field__leading--nudge", "data-test": "nudge-handle", "data-dragging": isDraggingNudge ? "true" : undefined, title: `Drag to adjust ${label ?? property}`, onPointerDown: handleDragNudgePointerDown, onPointerMove: handleDragNudgePointerMove, onPointerUp: handleDragNudgePointerEnd, onPointerCancel: handleDragNudgePointerEnd, onBlur: stopDragNudge, children: leading }));
426
+ return (_jsx("span", { className: "token-field__leading token-field__leading--nudge", "data-test": "nudge-handle", "data-dragging": isDraggingNudge ? "true" : undefined, onPointerDown: handleDragNudgePointerDown, onPointerMove: handleDragNudgePointerMove, onPointerUp: handleDragNudgePointerEnd, onPointerCancel: handleDragNudgePointerEnd, onBlur: stopDragNudge, children: leading }));
418
427
  }
419
428
  function commitOpacityValue(value = opacityValue) {
420
- if (!showOpacity || !onCommitOpacity)
429
+ if (fieldDisabled || !showOpacity || !onCommitOpacity)
421
430
  return;
422
431
  const normalized = normalizeOpacityPercent(value);
423
432
  if (normalized === null) {
@@ -430,7 +439,7 @@ export function TokenValueField(props) {
430
439
  }
431
440
  setOpacityValue(normalized);
432
441
  }
433
- const opacityControl = showOpacity ? (_jsx("input", { className: "token-opacity-input", "data-test": "color-opacity-input", type: "text", inputMode: "decimal", value: opacityValue, disabled: disabled || !onCommitOpacity, "aria-label": `Opacity for ${property}`, onChange: (event) => setOpacityValue(event.target.value), onBlur: () => commitOpacityValue(), onKeyDown: (event) => {
442
+ const opacityControl = showOpacity ? (_jsx("input", { className: "token-opacity-input", "data-test": "color-opacity-input", type: "text", inputMode: "decimal", value: opacityValue, disabled: fieldDisabled || !onCommitOpacity, "aria-label": `Opacity for ${property}`, onChange: (event) => setOpacityValue(event.target.value), onBlur: () => commitOpacityValue(), onKeyDown: (event) => {
434
443
  const direction = arrowDirection(event.key);
435
444
  if (direction && !event.altKey && !event.ctrlKey && !event.metaKey) {
436
445
  const next = nudgeOpacityValue(opacityValue, direction, event.shiftKey);
@@ -453,17 +462,17 @@ export function TokenValueField(props) {
453
462
  }
454
463
  } })) : null;
455
464
  const colorPreview = activeToken ? resolvedValue || activeToken.value : resolvedValue || rawValue;
456
- const colorControlEl = isColor ? (_jsx(NativeColorSwatch, { value: colorPreview, disabled: disabled, onChange: (value) => commitRawValue(value) })) : null;
465
+ const colorControlEl = isColor ? (_jsx(NativeColorSwatch, { value: colorPreview, disabled: fieldDisabled, onChange: (value) => commitRawValue(value) })) : null;
457
466
  const rawSuggestionItems = availableSuggestions.map(rawSuggestion);
458
467
  if (activeToken) {
459
468
  const chipValue = chipVariant === "small" ? stripCssUnit(activeToken.value) : activeToken.name;
460
469
  const embedColorSwatch = isColor && chipVariant !== "small";
461
- return (_jsxs("span", { className: `token-field${isColor ? " token-field--color" : ""}${embedColorSwatch ? " token-field--color-chip" : ""}${className ? ` ${className}` : ""}`, "data-test": "token-field", "data-property": property, "aria-label": label, title: label, children: [renderLeading(), embedColorSwatch ? null : colorControlEl, _jsxs(TokenChip, { size: chipVariant, "data-group": groupByTokenName.get(activeToken.name) ?? tokenGroup(activeToken), children: [_jsx(PopoverListbox, { query: "", value: activeToken.name, open: isTokenPickerOpen, trigger: (_jsxs(TokenChip.Picker, { children: [embedColorSwatch ? colorControlEl : null, _jsx(TokenChip.Label, { title: activeToken.name, children: chipValue })] })), triggerClassName: "token-chip__trigger", triggerDataTest: "token-chip", triggerAriaLabel: `Change ${property} token`, searchable: true, searchPlaceholder: "Search tokens\u2026", searchAriaLabel: "Search tokens", items: [...rawSuggestionItems, ...relevantTokens.map((entry) => tokenSuggestion(entry, groupByTokenName))], onQueryChange: () => undefined, onOpenChange: setTokenPickerOpen, disabled: disabled, onSelect: (value) => {
470
+ return (_jsxs("span", { className: cx("token-field", isColor && "token-field--color", embedColorSwatch && "token-field--color-chip", blockedBy !== null && "token-field--blocked", className), "data-test": "token-field", "data-property": property, "aria-disabled": fieldDisabled || undefined, "aria-label": label, children: [renderLeading(), embedColorSwatch ? null : colorControlEl, _jsxs(TokenChip, { size: chipVariant, "data-group": groupByTokenName.get(activeToken.name) ?? tokenGroup(activeToken), children: [_jsx(PopoverListbox, { query: "", value: activeToken.name, open: isTokenPickerOpen, trigger: (_jsxs(TokenChip.Picker, { children: [embedColorSwatch ? colorControlEl : null, _jsx(TokenChip.Label, { title: chipVariant === "small" ? activeToken.name : undefined, children: chipValue })] })), triggerClassName: "token-chip__trigger", triggerDataTest: "token-chip", triggerAriaLabel: `Change ${property} token`, searchable: true, searchPlaceholder: "Search tokens\u2026", searchAriaLabel: "Search tokens", items: [...rawSuggestionItems, ...relevantTokens.map((entry) => tokenSuggestion(entry, groupByTokenName))], onQueryChange: () => undefined, onOpenChange: setTokenPickerOpen, disabled: fieldDisabled, onSelect: (value) => {
462
471
  handleSuggestionSelect(value);
463
- } }), _jsx(TokenChip.Action, { children: _jsx(IconButton, { variant: "quiet", size: "compact", style: { borderRadius: "var(--radius-4)" }, label: "Replace with raw value", "data-test": "delink-btn", disabled: disabled, onClick: handleDelink, children: _jsx(IconLinkOff, { size: chipVariant === "small" ? 12 : 14, stroke: 1.75, "aria-hidden": "true" }) }) })] }), opacityControl, _jsx(AtRuleIndicator, { atRules: fieldAtRules }), trailing ? _jsx("span", { className: "token-field__trailing", children: trailing }) : null] }));
472
+ } }), _jsx(TokenChip.Action, { children: _jsx(Tooltip, { stableTrigger: true, children: _jsx(IconButton, { variant: "quiet", size: "compact", style: { borderRadius: "var(--radius-4)" }, label: "Replace with raw value", "data-test": "delink-btn", disabled: fieldDisabled, onClick: handleDelink, children: _jsx(IconLinkOff, { size: chipVariant === "small" ? 12 : 14, stroke: 1.75, "aria-hidden": "true" }) }) }) })] }), opacityControl, _jsx(AtRuleIndicator, { atRules: fieldAtRules }), trailing ? _jsx("span", { className: "token-field__trailing", children: trailing }) : null, _jsx(InlineStyleWarning, { blockedBy: blockedBy, dataTest: inlineWarningDataTest, tooltipDataTest: inlineWarningTooltipDataTest })] }));
464
473
  }
465
474
  const showPopover = isFocused && (filteredTokens.length > 0 || availableSuggestions.length > 0);
466
- return (_jsxs("span", { className: `token-field token-field--raw${isColor ? " token-field--color" : ""}${className ? ` ${className}` : ""}`, "data-test": "token-field", "data-property": property, "aria-label": label, title: label, children: [renderLeading(), colorControlEl, _jsx(PopoverListbox, { query: rawValue, value: null, open: showPopover, placeholder: property, inputRef: inputRef, inputAppearance: "embedded", inputDataTest: inputDataTest, inputOnFocus: () => {
475
+ return (_jsxs("span", { className: cx("token-field", "token-field--raw", isColor && "token-field--color", blockedBy !== null && "token-field--blocked", className), "data-test": "token-field", "data-property": property, "aria-disabled": fieldDisabled || undefined, "aria-label": label, children: [renderLeading(), colorControlEl, _jsx(PopoverListbox, { query: rawValue, value: null, open: showPopover, placeholder: property, inputRef: inputRef, inputAppearance: "embedded", inputDataTest: inputDataTest, inputOnFocus: () => {
467
476
  setIsFocused(true);
468
477
  if (mixed && rawValue.trim().toLowerCase() === "mixed")
469
478
  setRawValue("");
@@ -473,9 +482,9 @@ export function TokenValueField(props) {
473
482
  ], onQueryChange: (value) => {
474
483
  isNavigatingSuggestions.current = false;
475
484
  setRawValue(value);
476
- }, onOpenChange: setIsFocused, disabled: disabled, onSelect: (value) => {
485
+ }, onOpenChange: setIsFocused, disabled: fieldDisabled, onSelect: (value) => {
477
486
  handleSuggestionSelect(value);
478
- } }), opacityControl, _jsx(AtRuleIndicator, { atRules: fieldAtRules }), trailing ? _jsx("span", { className: "token-field__trailing", children: trailing }) : null] }));
487
+ } }), opacityControl, _jsx(AtRuleIndicator, { atRules: fieldAtRules }), trailing ? _jsx("span", { className: "token-field__trailing", children: trailing }) : null, _jsx(InlineStyleWarning, { blockedBy: blockedBy, dataTest: inlineWarningDataTest, tooltipDataTest: inlineWarningTooltipDataTest })] }));
479
488
  }
480
489
  function arrowDirection(key) {
481
490
  if (key === "ArrowUp")
@@ -485,7 +494,7 @@ function arrowDirection(key) {
485
494
  return null;
486
495
  }
487
496
  export function TokenField(props) {
488
- const { property, semanticSlot, tokenRow, selection, initialValue, displayValue, domElement: el, editTarget, entries, suggestions, inputDataTest, onAfterEdit, editMetadata, leading, trailing, className, label, chipVariant, formatRawValue: formatRawValueProp, disabled = false, mixed = false, attributionTokens, } = props;
497
+ const { property, semanticSlot, tokenRow, selection, initialValue, displayValue, domElement: el, editTarget, entries, suggestions, inputDataTest, onAfterEdit, editMetadata, leading, trailing, className, label, chipVariant, formatRawValue: formatRawValueProp, disabled = false, mixed = false, attributionTokens, inlineWarningDataTest, inlineWarningTooltipDataTest, } = props;
489
498
  const selectedProperty = selection && selection.elements.length > 1
490
499
  ? selection.getProperty(property)
491
500
  : null;
@@ -495,6 +504,7 @@ export function TokenField(props) {
495
504
  ? selectedProperty.value.value
496
505
  : undefined;
497
506
  const effectiveMetadata = editTarget && isMultiTarget(editTarget) ? undefined : editMetadata;
507
+ const blockedBy = inlineBlockedBy(selection?.domElements ?? [el], property);
498
508
  const tokenBackedOpacityName = tokenRow?.tokenName
499
509
  && tokenRow.opacity
500
510
  && tokenRow.opacity.tokenName !== tokenRow.tokenName
@@ -544,7 +554,7 @@ export function TokenField(props) {
544
554
  ?? (selectedProperty?.token.kind === "mixed" ? ["Mixed tokens"] : undefined)
545
555
  ?? (expression
546
556
  ? tokenRow?.tokens?.filter((token) => token.name !== tokenRow.opacity?.tokenName).map((token) => token.name)
547
- : undefined), opacity: tokenRow?.opacity, color: tokenRow?.color, entries: entries, suggestions: suggestions, inputDataTest: inputDataTest, disabled: disabled, mixed: effectiveMixed, isColor: selectTokens({ property, slot: semanticSlot, entries: [] }).preferredGroup === "color", formatRawValue: (value) => {
557
+ : undefined), opacity: tokenRow?.opacity, color: tokenRow?.color, entries: entries, suggestions: suggestions, inputDataTest: inputDataTest, disabled: disabled, blockedBy: blockedBy, mixed: effectiveMixed, isColor: selectTokens({ property, slot: semanticSlot, entries: [] }).preferredGroup === "color", formatRawValue: (value) => {
548
558
  if (formatRawValueProp)
549
559
  return formatRawValueProp(value);
550
560
  return completeCssValue(value.trim(), valuePolicyFor(property));
@@ -582,7 +592,7 @@ export function TokenField(props) {
582
592
  }, onUnlink: (value) => {
583
593
  setStyle(editTarget ?? el, property, value, effectiveMetadata);
584
594
  onAfterEdit?.();
585
- }, leading: leading, trailing: trailing, className: className, label: label, chipVariant: chipVariant }));
595
+ }, leading: leading, trailing: trailing, className: className, label: label, chipVariant: chipVariant, inlineWarningDataTest: inlineWarningDataTest, inlineWarningTooltipDataTest: inlineWarningTooltipDataTest }));
586
596
  }
587
597
  function tokenSuggestion(entry, groups) {
588
598
  return {
@@ -1,23 +1,14 @@
1
1
  import { jsx as _jsx } from "react/jsx-runtime";
2
- function textContent(children) {
3
- if (children === null || children === undefined || typeof children === "boolean")
4
- return "";
5
- if (typeof children === "string" || typeof children === "number" || typeof children === "bigint") {
6
- return String(children);
7
- }
8
- if (Array.isArray(children))
9
- return children.map(textContent).join("");
10
- return "";
11
- }
2
+ import { cx } from "../ui/classNames.js";
3
+ import { Tooltip } from "../ui/Tooltip.js";
12
4
  export function TokenLabel({ as = "span", className, children, title, ...props }) {
13
- const childText = textContent(children);
14
5
  const labelProps = {
15
6
  ...props,
16
- className: `token-label${className ? ` ${className}` : ""}`,
17
- title: title ?? childText,
7
+ className: cx("token-label", className),
18
8
  };
19
9
  const content = _jsx("span", { className: "token-label__content", children: children });
20
- return as === "code"
10
+ const label = as === "code"
21
11
  ? _jsx("code", { ...labelProps, children: content })
22
12
  : _jsx("span", { ...labelProps, children: content });
13
+ return title === undefined ? label : _jsx(Tooltip, { content: title, children: label });
23
14
  }
@@ -2,7 +2,7 @@ import type { TokenEntry } from "../../css/model/index.js";
2
2
  import type { ElementChangeRecord } from "../changes/changesLog.js";
3
3
  import { type EditTarget } from "../selection/editTarget.js";
4
4
  export type { ChangeRecord } from "../changes/changesLog.js";
5
- export { getPendingRules, getChangesList as getChangeRecords, clearWorkspace as resetPendingRules } from "../changes/changesLog.js";
5
+ export { getPendingRules, getChangesList as getChangeRecords, clearActiveDraft as resetPendingRules } from "../changes/changesLog.js";
6
6
  export interface StyleEditMetadata {
7
7
  sourceProperty?: string;
8
8
  sourceAuthoredValue?: string;
@@ -42,9 +42,13 @@ function sourceFields(el) {
42
42
  file: parsed.file,
43
43
  line: parsed.line,
44
44
  column: parsed.column,
45
+ sourceEvidence: {
46
+ tagName: normalizeRuntimeTag(el.tagName),
47
+ props: boundRuntimeEvidence(el.getAttribute("data-cprops")),
48
+ },
45
49
  };
46
50
  }
47
- export { getPendingRules, getChangesList as getChangeRecords, clearWorkspace as resetPendingRules } from "../changes/changesLog.js";
51
+ export { getPendingRules, getChangesList as getChangeRecords, clearActiveDraft as resetPendingRules } from "../changes/changesLog.js";
48
52
  /** Returns whether a style write can address every element in the target safely. */
49
53
  export function canEditStyles(target) {
50
54
  return canPlanBatchEditScopes(targetElements(target));
@@ -87,6 +91,7 @@ export function swapTokens(target, changes) {
87
91
  newToken: change.newToken,
88
92
  source: { file: source.file, line: source.line, component: cid },
89
93
  runtimeEvidence: source.runtimeEvidence,
94
+ sourceEvidence: source.sourceEvidence,
90
95
  state,
91
96
  ...scopePlan.get(el),
92
97
  };
@@ -155,6 +160,7 @@ function buildStyleRecord(el, scopePlan, { property, value, oldRawValue, metadat
155
160
  oldRawValue: (oldRawValue ?? getStateStyleValue(el, property)) || undefined,
156
161
  source: { file: source.file, line: source.line, component: cid },
157
162
  runtimeEvidence: source.runtimeEvidence,
163
+ sourceEvidence: source.sourceEvidence,
158
164
  state,
159
165
  ...scopePlan.get(el),
160
166
  };
@@ -1,6 +1,7 @@
1
- import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
2
  import { createContext, useContext, useMemo } from "react";
3
- import { Tooltip } from "@base-ui/react/tooltip";
3
+ import { Tooltip } from "./Tooltip.js";
4
+ import { cx } from "./classNames.js";
4
5
  const EMPTY_AT_RULES = [];
5
6
  const FieldAtRuleContext = createContext(new Map());
6
7
  /**
@@ -40,9 +41,6 @@ function countLabel(label, count) {
40
41
  const noun = label.toLowerCase().replace(/query$/, count === 1 ? "query" : "queries");
41
42
  return `${count} ${noun}`;
42
43
  }
43
- function portalContainer() {
44
- return document.getElementById("nudge-ui-root")?.shadowRoot ?? document.body;
45
- }
46
44
  /** Compact, field-level attribution for the conditional rule that currently wins. */
47
45
  export function AtRuleIndicator({ atRules = EMPTY_AT_RULES, className }) {
48
46
  if (atRules.length === 0)
@@ -50,5 +48,5 @@ export function AtRuleIndicator({ atRules = EMPTY_AT_RULES, className }) {
50
48
  const label = labelFor(atRules);
51
49
  const activeCount = atRules.filter((atRule) => !("active" in atRule) || atRule.active).length;
52
50
  const count = countLabel(label, atRules.length);
53
- return (_jsx(Tooltip.Provider, { children: _jsxs(Tooltip.Root, { disableHoverablePopup: true, children: [_jsx(Tooltip.Trigger, { type: "button", delay: 0, className: `at-rule-indicator${className ? ` ${className}` : ""}`, "data-test": "at-rule-indicator", "aria-label": activeCount > 0 ? `Active ${count}` : count, children: _jsx("span", { className: "at-rule-indicator__symbol", "aria-hidden": "true", children: atRules.length }) }), _jsx(Tooltip.Portal, { container: portalContainer(), children: _jsx(Tooltip.Positioner, { className: "at-rule-tooltip-positioner", side: "top", align: "end", sideOffset: 7, children: _jsx(Tooltip.Popup, { className: "at-rule-tooltip", "data-test": "at-rule-tooltip", children: _jsx("div", { className: "at-rule-tooltip__rules", children: atRules.map((atRule, index) => (_jsx("div", { className: `at-rule-tooltip__rule${!("active" in atRule) || atRule.active ? " at-rule-tooltip__rule--active" : ""}`, "data-active": !("active" in atRule) || atRule.active ? "true" : "false", children: _jsx("code", { children: atRule.params }) }, `${atRule.kind}-${atRule.params}-${index}`))) }) }) }) })] }) }));
51
+ return (_jsx(Tooltip, { content: (_jsx("div", { className: "at-rule-tooltip__rules", children: atRules.map((atRule, index) => (_jsx("div", { className: cx("at-rule-tooltip__rule", (!("active" in atRule) || atRule.active) && "at-rule-tooltip__rule--active"), "data-active": !("active" in atRule) || atRule.active ? "true" : "false", children: _jsx("code", { children: atRule.params }) }, `${atRule.kind}-${atRule.params}-${index}`))) })), delay: 0, positionerClassName: "at-rule-tooltip-positioner", popupClassName: "at-rule-tooltip", "data-test": "at-rule-tooltip", children: _jsx("button", { type: "button", className: cx("at-rule-indicator", className), "data-test": "at-rule-indicator", "aria-label": activeCount > 0 ? `Active ${count}` : count, children: _jsx("span", { className: "at-rule-indicator__symbol", "aria-hidden": "true", children: atRules.length }) }) }));
54
52
  }
@@ -1,4 +1,4 @@
1
- import type { ButtonHTMLAttributes, ReactElement } from "react";
1
+ import type { ButtonHTMLAttributes } from "react";
2
2
  export type ButtonVariant = "primary" | "secondary" | "quiet" | "danger" | "disabled";
3
3
  export type ButtonSize = "default" | "compact" | "large";
4
4
  export type ButtonProps = ButtonHTMLAttributes<HTMLButtonElement> & {
@@ -6,4 +6,8 @@ export type ButtonProps = ButtonHTMLAttributes<HTMLButtonElement> & {
6
6
  size?: ButtonSize;
7
7
  "data-test"?: string;
8
8
  };
9
- export declare function Button({ variant, size, className, ...props }: ButtonProps): ReactElement;
9
+ export declare const Button: import("react").ForwardRefExoticComponent<ButtonHTMLAttributes<HTMLButtonElement> & {
10
+ variant?: ButtonVariant;
11
+ size?: ButtonSize;
12
+ "data-test"?: string;
13
+ } & import("react").RefAttributes<HTMLButtonElement>>;
@@ -1,4 +1,5 @@
1
1
  import { jsx as _jsx } from "react/jsx-runtime";
2
- export function Button({ variant = "secondary", size = "default", className, ...props }) {
3
- return (_jsx("button", { ...props, className: `button button--${variant} button--${size}${className ? ` ${className}` : ""}` }));
4
- }
2
+ import { forwardRef } from "react";
3
+ export const Button = forwardRef(function Button({ variant = "secondary", size = "default", className, ...props }, ref) {
4
+ return (_jsx("button", { ref: ref, ...props, className: `button button--${variant} button--${size}${className ? ` ${className}` : ""}` }));
5
+ });
@@ -1,4 +1,4 @@
1
- import type { HTMLAttributes, ReactElement, ReactNode } from "react";
1
+ import type { HTMLAttributes, ReactNode } from "react";
2
2
  /**
3
3
  * Visual boundary for an inspector control. It owns the shared control chrome
4
4
  * while the child owns its particular input or selection behaviour.
@@ -11,4 +11,4 @@ export interface ControlSurfaceProps extends HTMLAttributes<HTMLSpanElement> {
11
11
  "data-test"?: string;
12
12
  children?: ReactNode;
13
13
  }
14
- export declare function ControlSurface({ appearance, density, className, children, ...props }: ControlSurfaceProps): ReactElement;
14
+ export declare const ControlSurface: import("react").ForwardRefExoticComponent<ControlSurfaceProps & import("react").RefAttributes<HTMLSpanElement>>;
@@ -1,10 +1,11 @@
1
1
  import { jsx as _jsx } from "react/jsx-runtime";
2
- export function ControlSurface({ appearance = "default", density = "default", className, children, ...props }) {
2
+ import { forwardRef } from "react";
3
+ export const ControlSurface = forwardRef(function ControlSurface({ appearance = "default", density = "default", className, children, ...props }, ref) {
3
4
  const classes = [
4
5
  "control-surface",
5
6
  appearance === "embedded" ? "control-surface--embedded" : "",
6
7
  density === "compact" ? "control-surface--compact" : "",
7
8
  className ?? "",
8
9
  ].filter(Boolean).join(" ");
9
- return _jsx("span", { ...props, className: classes, children: children });
10
- }
10
+ return _jsx("span", { ref: ref, ...props, className: classes, children: children });
11
+ });
@@ -0,0 +1,11 @@
1
+ import type { ReactElement } from "react";
2
+ export interface InlineStyleWarningProps {
3
+ /** Inline declaration blocking the field; renders nothing when null. */
4
+ blockedBy: string | null;
5
+ dataTest?: string;
6
+ tooltipDataTest?: string;
7
+ className?: string;
8
+ symbolClassName?: string;
9
+ }
10
+ export declare function inlineStyleWarningContent(blockedBy: string | null): ReactElement | undefined;
11
+ export declare function InlineStyleWarning({ blockedBy, dataTest, tooltipDataTest, className, symbolClassName, }: InlineStyleWarningProps): ReactElement | null;
@@ -0,0 +1,13 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { cx } from "./classNames.js";
3
+ import { Tooltip } from "./Tooltip.js";
4
+ export function inlineStyleWarningContent(blockedBy) {
5
+ if (blockedBy === null)
6
+ return undefined;
7
+ return (_jsx("div", { className: "at-rule-tooltip__rules", children: _jsxs("div", { className: "at-rule-tooltip__rule at-rule-tooltip__rule--active", children: ["Set inline (", _jsx("code", { children: blockedBy }), "). Previews can't beat inline styles \u2014 move it to a stylesheet to edit it here."] }) }));
8
+ }
9
+ export function InlineStyleWarning({ blockedBy, dataTest = "inline-style-warning", tooltipDataTest, className, symbolClassName, }) {
10
+ if (blockedBy === null)
11
+ return null;
12
+ return (_jsx(Tooltip, { content: inlineStyleWarningContent(blockedBy), delay: 0, positionerClassName: "at-rule-tooltip-positioner", popupClassName: "at-rule-tooltip", "data-test": tooltipDataTest, children: _jsx("button", { type: "button", className: cx("inline-style-warning", className), "data-test": dataTest, "aria-label": `Blocked by inline style: ${blockedBy}`, children: _jsx("span", { className: cx("inline-style-warning__symbol", symbolClassName), "aria-hidden": "true", children: "!" }) }) }));
13
+ }
@@ -7,6 +7,7 @@ export interface InspectorPopoverProps {
7
7
  side?: "top" | "bottom" | "left" | "right";
8
8
  align?: "start" | "center" | "end";
9
9
  sideOffset?: number;
10
+ triggerTooltip?: ReactNode;
10
11
  "data-test"?: string;
11
12
  }
12
13
  /**
@@ -14,4 +15,4 @@ export interface InspectorPopoverProps {
14
15
  * listbox popover, this leaves the popup content to the caller for compound
15
16
  * settings panels and field controls.
16
17
  */
17
- export declare function InspectorPopover({ triggerElement, children, open, onOpenChange, side, align, sideOffset, "data-test": dataTest, }: InspectorPopoverProps): ReactElement;
18
+ export declare function InspectorPopover({ triggerElement, children, open, onOpenChange, side, align, sideOffset, triggerTooltip, "data-test": dataTest, }: InspectorPopoverProps): ReactElement;
@@ -1,13 +1,12 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import { Popover as BasePopover } from "@base-ui/react/popover";
3
+ import { Tooltip } from "./Tooltip.js";
4
+ import { portalContainer } from "./portalContainer.js";
3
5
  /**
4
6
  * Base UI popover anchored inside the inspector shadow root. Unlike the
5
7
  * listbox popover, this leaves the popup content to the caller for compound
6
8
  * settings panels and field controls.
7
9
  */
8
- export function InspectorPopover({ triggerElement, children, open, onOpenChange, side = "bottom", align = "center", sideOffset = 6, "data-test": dataTest, }) {
9
- const portalContainer = typeof document !== "undefined"
10
- ? document.getElementById("nudge-ui-root")?.shadowRoot ?? document.body
11
- : null;
12
- return (_jsxs(BasePopover.Root, { open: open, onOpenChange: onOpenChange, children: [_jsx(BasePopover.Trigger, { render: triggerElement, "data-test": dataTest }), _jsx(BasePopover.Portal, { container: portalContainer, children: _jsx(BasePopover.Positioner, { className: "inspector-popover__positioner", side: side, align: align, sideOffset: sideOffset, children: _jsx(BasePopover.Popup, { className: "inspector-popover__popup", "data-test": dataTest ? `${dataTest}-popover` : undefined, children: children }) }) })] }));
10
+ export function InspectorPopover({ triggerElement, children, open, onOpenChange, side = "bottom", align = "center", sideOffset = 6, triggerTooltip, "data-test": dataTest, }) {
11
+ return (_jsxs(BasePopover.Root, { open: open, onOpenChange: onOpenChange, children: [_jsx(Tooltip, { content: triggerTooltip, disabled: triggerTooltip === undefined, children: _jsx(BasePopover.Trigger, { render: triggerElement, "data-test": dataTest }) }), _jsx(BasePopover.Portal, { container: portalContainer(), children: _jsx(BasePopover.Positioner, { className: "inspector-popover__positioner", side: side, align: align, sideOffset: sideOffset, children: _jsx(BasePopover.Popup, { className: "inspector-popover__popup", "data-test": dataTest ? `${dataTest}-popover` : undefined, children: children }) }) })] }));
13
12
  }
@@ -17,6 +17,7 @@ export interface PopoverListboxProps {
17
17
  triggerClassName?: string;
18
18
  triggerDataTest?: string;
19
19
  triggerAriaLabel?: string;
20
+ triggerTooltip?: ReactNode;
20
21
  searchable?: boolean;
21
22
  searchPlaceholder?: string;
22
23
  searchAriaLabel?: string;
@@ -34,4 +35,4 @@ export interface PopoverListboxProps {
34
35
  onOpenChange: (open: boolean) => void;
35
36
  onSelect: (value: string) => void;
36
37
  }
37
- export declare function PopoverListbox({ value, query, items, open, trigger, triggerElement, triggerClassName, triggerDataTest, triggerAriaLabel, searchable, searchPlaceholder, searchAriaLabel, placeholder, inputRef, inputClassName, inputAppearance, inputDataTest, inputOnFocus, inputOnBlur, inputOnKeyDown, disabled, className, onQueryChange, onOpenChange, onSelect, }: PopoverListboxProps): ReactElement;
38
+ export declare function PopoverListbox({ value, query, items, open, trigger, triggerElement, triggerClassName, triggerDataTest, triggerAriaLabel, triggerTooltip, searchable, searchPlaceholder, searchAriaLabel, placeholder, inputRef, inputClassName, inputAppearance, inputDataTest, inputOnFocus, inputOnBlur, inputOnKeyDown, disabled, className, onQueryChange, onOpenChange, onSelect, }: PopoverListboxProps): ReactElement;
@@ -1,21 +1,22 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
2
  import { Combobox } from "@base-ui/react/combobox";
3
3
  import { Autocomplete } from "@base-ui/react/autocomplete";
4
- export function PopoverListbox({ value = null, query, items, open, trigger, triggerElement, triggerClassName, triggerDataTest, triggerAriaLabel, searchable = false, searchPlaceholder = "Search…", searchAriaLabel = "Search options", placeholder, inputRef, inputClassName, inputAppearance = "default", inputDataTest, inputOnFocus, inputOnBlur, inputOnKeyDown, disabled = false, className, onQueryChange, onOpenChange, onSelect, }) {
5
- const portalContainer = typeof document !== "undefined"
6
- ? document.getElementById("nudge-ui-root")?.shadowRoot ?? document.body
7
- : null;
4
+ import { cx } from "./classNames.js";
5
+ import { Tooltip } from "./Tooltip.js";
6
+ import { portalContainer } from "./portalContainer.js";
7
+ export function PopoverListbox({ value = null, query, items, open, trigger, triggerElement, triggerClassName, triggerDataTest, triggerAriaLabel, triggerTooltip, searchable = false, searchPlaceholder = "Search…", searchAriaLabel = "Search options", placeholder, inputRef, inputClassName, inputAppearance = "default", inputDataTest, inputOnFocus, inputOnBlur, inputOnKeyDown, disabled = false, className, onQueryChange, onOpenChange, onSelect, }) {
8
8
  const itemByValue = new Map(items.map((item) => [item.value, item]));
9
+ const resolvedTriggerTooltip = triggerTooltip ?? (triggerElement ? triggerAriaLabel : undefined);
9
10
  function renderComboboxItem(item) {
10
11
  return (_jsxs(Combobox.Item, { value: item.value, className: "popover-listbox__item", "data-test": item["data-test"], children: [item.leading ? _jsx("span", { className: "popover-listbox__leading", children: item.leading }) : null, _jsx("span", { className: "popover-listbox__label", children: item.label }), item.trailing ? _jsx("span", { className: "popover-listbox__trailing", children: item.trailing }) : null] }, item.value));
11
12
  }
12
- return (_jsx("div", { className: `popover-listbox${className ? ` ${className}` : ""}`, children: trigger || triggerElement ? (_jsxs(Combobox.Root, { value: value, inputValue: searchable ? undefined : query, open: open, items: items.map((item) => item.value), filteredItems: searchable ? undefined : items.map((item) => item.value), autoHighlight: true, itemToStringLabel: (item) => itemByValue.get(item)?.label ?? item, onInputValueChange: (next) => onQueryChange(next), onOpenChange: (next) => onOpenChange(next), onValueChange: (next) => {
13
+ return (_jsx("div", { className: cx("popover-listbox", className), children: trigger || triggerElement ? (_jsxs(Combobox.Root, { value: value, inputValue: searchable ? undefined : query, open: open, items: items.map((item) => item.value), filteredItems: searchable ? undefined : items.map((item) => item.value), autoHighlight: true, itemToStringLabel: (item) => itemByValue.get(item)?.label ?? item, onInputValueChange: (next) => onQueryChange(next), onOpenChange: (next) => onOpenChange(next), onValueChange: (next) => {
13
14
  if (typeof next === "string")
14
15
  onSelect(next);
15
- }, children: [triggerElement ? (_jsx(Combobox.Trigger, { render: triggerElement, className: `popover-listbox__trigger${triggerClassName ? ` ${triggerClassName}` : ""}`, "data-test": triggerDataTest, "aria-label": triggerAriaLabel, disabled: disabled })) : (_jsx(Combobox.Trigger, { className: `popover-listbox__trigger${triggerClassName ? ` ${triggerClassName}` : ""}`, "data-test": triggerDataTest, "aria-label": triggerAriaLabel, disabled: disabled, children: trigger })), _jsx(Combobox.Portal, { container: portalContainer, children: _jsx(Combobox.Positioner, { className: "popover-listbox__positioner", children: _jsxs(Combobox.Popup, { className: `popover-listbox__popup${searchable ? " popover-listbox__popup--searchable" : ""}`, children: [searchable ? (_jsxs(_Fragment, { children: [_jsx(Combobox.Input, { className: "popover-listbox__search-input", placeholder: searchPlaceholder, "aria-label": searchAriaLabel, "data-test": triggerDataTest ? `${triggerDataTest}-search` : "popover-listbox-search" }), _jsx(Combobox.Empty, { className: "popover-listbox__empty", children: "No matching options." })] })) : null, _jsx(Combobox.List, { className: `popover-listbox__list${searchable ? " popover-listbox__list--searchable" : ""}`, children: searchable
16
+ }, children: [_jsx(Tooltip, { content: resolvedTriggerTooltip, disabled: resolvedTriggerTooltip === undefined, stableTrigger: true, children: _jsx(Combobox.Trigger, { render: triggerElement, className: cx("popover-listbox__trigger", triggerClassName), "data-test": triggerDataTest, "aria-label": triggerAriaLabel, disabled: disabled, children: triggerElement ? undefined : trigger }) }), _jsx(Combobox.Portal, { container: portalContainer(), children: _jsx(Combobox.Positioner, { className: "popover-listbox__positioner", children: _jsxs(Combobox.Popup, { className: cx("popover-listbox__popup", searchable && "popover-listbox__popup--searchable"), children: [searchable ? (_jsxs(_Fragment, { children: [_jsx(Combobox.Input, { className: "popover-listbox__search-input", placeholder: searchPlaceholder, "aria-label": searchAriaLabel, "data-test": triggerDataTest ? `${triggerDataTest}-search` : "popover-listbox-search" }), _jsx(Combobox.Empty, { className: "popover-listbox__empty", children: "No matching options." })] })) : null, _jsx(Combobox.List, { className: cx("popover-listbox__list", searchable && "popover-listbox__list--searchable"), children: searchable
16
17
  ? ((itemValue) => {
17
18
  const item = itemByValue.get(itemValue);
18
19
  return item ? renderComboboxItem(item) : null;
19
20
  })
20
- : items.map((item) => renderComboboxItem(item)) })] }) }) })] })) : (_jsxs(Autocomplete.Root, { value: query, open: open, items: items.map((item) => item.value), filteredItems: items.map((item) => item.value), autoHighlight: true, mode: "none", openOnInputClick: true, onValueChange: onQueryChange, onOpenChange: (next) => onOpenChange(next), children: [_jsx(Autocomplete.Input, { ref: inputRef, className: `text-input${inputAppearance === "embedded" ? " text-input--embedded" : ""}${inputClassName ? ` ${inputClassName}` : ""}`, placeholder: placeholder, "data-test": inputDataTest, onFocus: inputOnFocus, onBlur: inputOnBlur, onKeyDownCapture: inputOnKeyDown, disabled: disabled }), _jsx(Autocomplete.Portal, { container: portalContainer, children: _jsx(Autocomplete.Positioner, { className: "popover-listbox__positioner", children: _jsx(Autocomplete.Popup, { className: "popover-listbox__popup", children: _jsx(Autocomplete.List, { className: "popover-listbox__list", children: items.map((item) => (_jsxs(Autocomplete.Item, { value: item.value, className: "popover-listbox__item", "data-test": item["data-test"], onClick: () => onSelect(item.value), children: [item.leading ? _jsx("span", { className: "popover-listbox__leading", children: item.leading }) : null, _jsx("span", { className: "popover-listbox__label", children: item.label }), item.trailing ? _jsx("span", { className: "popover-listbox__trailing", children: item.trailing }) : null] }, item.value))) }) }) }) })] })) }));
21
+ : items.map((item) => renderComboboxItem(item)) })] }) }) })] })) : (_jsxs(Autocomplete.Root, { value: query, open: open, items: items.map((item) => item.value), filteredItems: items.map((item) => item.value), autoHighlight: true, mode: "none", openOnInputClick: true, onValueChange: onQueryChange, onOpenChange: (next) => onOpenChange(next), children: [_jsx(Autocomplete.Input, { ref: inputRef, className: cx("text-input", inputAppearance === "embedded" && "text-input--embedded", inputClassName), placeholder: placeholder, "data-test": inputDataTest, onFocus: inputOnFocus, onBlur: inputOnBlur, onKeyDownCapture: inputOnKeyDown, disabled: disabled }), _jsx(Autocomplete.Portal, { container: portalContainer(), children: _jsx(Autocomplete.Positioner, { className: "popover-listbox__positioner", children: _jsx(Autocomplete.Popup, { className: "popover-listbox__popup", children: _jsx(Autocomplete.List, { className: "popover-listbox__list", children: items.map((item) => (_jsxs(Autocomplete.Item, { value: item.value, className: "popover-listbox__item", "data-test": item["data-test"], onClick: () => onSelect(item.value), children: [item.leading ? _jsx("span", { className: "popover-listbox__leading", children: item.leading }) : null, _jsx("span", { className: "popover-listbox__label", children: item.label }), item.trailing ? _jsx("span", { className: "popover-listbox__trailing", children: item.trailing }) : null] }, item.value))) }) }) }) })] })) }));
21
22
  }
@@ -14,11 +14,12 @@ interface SegmentedControlProps<T extends string> {
14
14
  "data-test"?: string;
15
15
  "data-property"?: string;
16
16
  className?: string;
17
+ disabled?: boolean;
17
18
  /** Allows the active option to be cleared by clicking it again. */
18
19
  allowDeselect?: boolean;
19
20
  /** Restores the value represented by an unselected control. */
20
21
  onDeselect?: () => void;
21
22
  }
22
23
  /** A compact single-choice control for adjacent, peer actions. */
23
- export declare function SegmentedControl<T extends string>({ value, options, onChange, "aria-label": ariaLabel, "data-test": dataTest, "data-property": dataProperty, className, allowDeselect, onDeselect, }: SegmentedControlProps<T>): ReactElement;
24
+ export declare function SegmentedControl<T extends string>({ value, options, onChange, "aria-label": ariaLabel, "data-test": dataTest, "data-property": dataProperty, className, disabled, allowDeselect, onDeselect, }: SegmentedControlProps<T>): ReactElement;
24
25
  export {};
@@ -1,10 +1,10 @@
1
1
  import { jsx as _jsx } from "react/jsx-runtime";
2
2
  import { Toggle } from "@base-ui/react/toggle";
3
3
  /** A compact single-choice control for adjacent, peer actions. */
4
- export function SegmentedControl({ value, options, onChange, "aria-label": ariaLabel, "data-test": dataTest, "data-property": dataProperty, className, allowDeselect = false, onDeselect, }) {
4
+ export function SegmentedControl({ value, options, onChange, "aria-label": ariaLabel, "data-test": dataTest, "data-property": dataProperty, className, disabled = false, allowDeselect = false, onDeselect, }) {
5
5
  return (_jsx("div", { className: `segmented-control${className ? ` ${className}` : ""}`, role: "group", "aria-label": ariaLabel, "data-test": dataTest, "data-property": dataProperty, children: options.map((option) => {
6
6
  const selected = option.value === value;
7
- return (_jsx(Toggle, { type: "button", className: `button segmented-control__button${selected ? " segmented-control__button--selected" : ""}`, pressed: selected, "aria-label": option.label, title: option.label, "data-test": option.testId, "data-active": selected ? "true" : "false", onPressedChange: (pressed) => {
7
+ return (_jsx(Toggle, { type: "button", className: `button segmented-control__button${selected ? " segmented-control__button--selected" : ""}`, pressed: selected, disabled: disabled, "aria-label": option.label, "data-test": option.testId, "data-active": selected ? "true" : "false", onPressedChange: (pressed) => {
8
8
  if (pressed) {
9
9
  onChange(option.value);
10
10
  }
@@ -1,4 +1,5 @@
1
- import type { ButtonHTMLAttributes, ReactElement } from "react";
1
+ import { Select as BaseSelect } from "@base-ui/react/select";
2
+ import type { ButtonHTMLAttributes, ComponentProps, ReactElement } from "react";
2
3
  import type { ControlAppearance } from "./ControlSurface.js";
3
4
  export interface SelectOption {
4
5
  value: string;
@@ -15,7 +16,11 @@ export type SelectProps = Omit<ButtonHTMLAttributes<HTMLButtonElement>, "onChang
15
16
  groups?: SelectGroup[];
16
17
  placeholder?: string;
17
18
  compact?: boolean;
19
+ /** Uses the shared icon button as the trigger; requires an accessible label. */
20
+ iconOnly?: boolean;
18
21
  appearance?: ControlAppearance;
22
+ /** Overrides popup placement, including text alignment for icon-only triggers. */
23
+ popupPosition?: Pick<ComponentProps<typeof BaseSelect.Positioner>, "side" | "align" | "alignItemWithTrigger">;
19
24
  searchable?: boolean;
20
25
  searchPlaceholder?: string;
21
26
  searchAriaLabel?: string;
@@ -2,25 +2,24 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import { Select as BaseSelect } from "@base-ui/react/select";
3
3
  import { Combobox as BaseCombobox } from "@base-ui/react/combobox";
4
4
  import { IconCheck, IconChevronDown } from "@tabler/icons-react";
5
+ import { portalContainer } from "./portalContainer.js";
6
+ import { IconButton } from "./IconButton.js";
5
7
  export function Select(props) {
6
8
  if (props.searchable)
7
9
  return _jsx(SearchableSelect, { ...props });
8
10
  return _jsx(NativeSelect, { ...props });
9
11
  }
10
- function NativeSelect({ value, options = [], groups = [], placeholder, compact, appearance = "default", searchable: _searchable, searchPlaceholder: _searchPlaceholder, searchAriaLabel: _searchAriaLabel, className, disabled, children, ...props }) {
12
+ function NativeSelect({ value, options = [], groups = [], placeholder, compact, iconOnly, appearance = "default", popupPosition, searchable: _searchable, searchPlaceholder: _searchPlaceholder, searchAriaLabel: _searchAriaLabel, className, disabled, children, ...props }) {
11
13
  const allOptions = [...options, ...groups.flatMap((group) => group.options)];
12
14
  const selectedOption = allOptions.find((option) => option.value === value);
13
- const portalContainer = typeof document !== "undefined"
14
- ? document.getElementById("nudge-ui-root")?.shadowRoot ?? document.body
15
- : null;
16
15
  function handleValueChange(next) {
17
16
  if (typeof next === "string")
18
17
  props.onValueChange?.(next);
19
18
  }
20
19
  const { onValueChange: _onValueChange, ...triggerProps } = props;
21
- return (_jsxs(BaseSelect.Root, { value: value || null, disabled: disabled, items: allOptions.map((option) => ({ value: option.value, label: option.label })), onValueChange: handleValueChange, children: [_jsxs(BaseSelect.Trigger, { ...triggerProps, disabled: disabled, className: `select${compact ? " select--compact" : ""}${appearance === "embedded" ? " select--embedded" : ""}${className ? ` ${className}` : ""}`, children: [_jsx(BaseSelect.Value, { className: "select__value", placeholder: placeholder, children: selectedOption?.label ?? (value || undefined) }), _jsx(BaseSelect.Icon, { className: "select__icon", children: _jsx(IconChevronDown, { size: 15, stroke: 1.8, "aria-hidden": "true" }) }), children] }), _jsx(BaseSelect.Portal, { container: portalContainer, children: _jsx(BaseSelect.Positioner, { className: "select__positioner", sideOffset: 4, children: _jsx(BaseSelect.Popup, { className: "select__popup", children: _jsxs(BaseSelect.List, { className: "select__list", children: [options.map((option) => _jsx(SelectItem, { option: option }, option.value)), groups.map((group) => (_jsxs(BaseSelect.Group, { className: "select__group", children: [_jsx(BaseSelect.GroupLabel, { className: "select__group-label", children: group.label }), group.options.map((option) => _jsx(SelectItem, { option: option }, `${group.label}-${option.value}`))] }, group.label)))] }) }) }) })] }));
20
+ return (_jsxs(BaseSelect.Root, { value: value || null, disabled: disabled, items: allOptions.map((option) => ({ value: option.value, label: option.label })), onValueChange: handleValueChange, children: [_jsxs(BaseSelect.Trigger, { ...triggerProps, render: iconOnly ? _jsx(IconButton, { label: props["aria-label"] ?? "Select option" }) : undefined, disabled: disabled, className: `select${iconOnly ? " select--icon-only" : ""}${compact ? " select--compact" : ""}${appearance === "embedded" ? " select--embedded" : ""}${className ? ` ${className}` : ""}`, children: [_jsx(BaseSelect.Value, { className: "select__value", placeholder: placeholder, children: selectedOption?.label ?? (value || undefined) }), _jsx(BaseSelect.Icon, { className: "select__icon", children: _jsx(IconChevronDown, { size: 15, stroke: 1.8, "aria-hidden": "true" }) }), children] }), _jsx(BaseSelect.Portal, { container: portalContainer(), children: _jsx(BaseSelect.Positioner, { className: "select__positioner", sideOffset: 4, ...popupPosition, alignItemWithTrigger: iconOnly ? false : popupPosition?.alignItemWithTrigger, children: _jsx(BaseSelect.Popup, { className: "select__popup", children: _jsxs(BaseSelect.List, { className: "select__list", children: [options.map((option) => _jsx(SelectItem, { option: option }, option.value)), groups.map((group) => (_jsxs(BaseSelect.Group, { className: "select__group", children: [_jsx(BaseSelect.GroupLabel, { className: "select__group-label", children: group.label }), group.options.map((option) => _jsx(SelectItem, { option: option }, `${group.label}-${option.value}`))] }, group.label)))] }) }) }) })] }));
22
21
  }
23
- function SearchableSelect({ value, options = [], groups = [], placeholder, compact, appearance = "default", searchable: _searchable, searchPlaceholder = "Search…", searchAriaLabel = "Search options", className, disabled, children, "data-test": dataTest, ...props }) {
22
+ function SearchableSelect({ value, options = [], groups = [], placeholder, compact, iconOnly, appearance = "default", popupPosition, searchable: _searchable, searchPlaceholder = "Search…", searchAriaLabel = "Search options", className, disabled, children, "data-test": dataTest, ...props }) {
24
23
  const allOptions = [...options, ...groups.flatMap((group) => group.options)];
25
24
  const selectedOption = allOptions.find((option) => option.value === value);
26
25
  const optionByValue = new Map(allOptions.map((option) => [option.value, option]));
@@ -34,16 +33,13 @@ function SearchableSelect({ value, options = [], groups = [], placeholder, compa
34
33
  items: group.options.map((option) => option.value),
35
34
  })),
36
35
  ];
37
- const portalContainer = typeof document !== "undefined"
38
- ? document.getElementById("nudge-ui-root")?.shadowRoot ?? document.body
39
- : null;
40
36
  function handleValueChange(next) {
41
37
  if (typeof next === "string")
42
38
  props.onValueChange?.(next);
43
39
  }
44
40
  const { onValueChange: _onValueChange, ...triggerProps } = props;
45
- const triggerClassName = `select${compact ? " select--compact" : ""}${appearance === "embedded" ? " select--embedded" : ""}${className ? ` ${className}` : ""}`;
46
- return (_jsxs(BaseCombobox.Root, { value: value || null, disabled: disabled, items: searchableGroups, itemToStringLabel: (item) => optionByValue.get(item)?.label ?? item, autoHighlight: true, onValueChange: handleValueChange, children: [_jsxs(BaseCombobox.Trigger, { ...triggerProps, "data-test": dataTest, disabled: disabled, className: triggerClassName, children: [_jsx("span", { className: "select__value", children: _jsx(BaseCombobox.Value, { placeholder: placeholder, children: selectedOption?.label ?? (value || undefined) }) }), _jsx(BaseCombobox.Icon, { className: "select__icon", children: _jsx(IconChevronDown, { size: 15, stroke: 1.8, "aria-hidden": "true" }) }), children] }), _jsx(BaseCombobox.Portal, { container: portalContainer, children: _jsx(BaseCombobox.Positioner, { className: "select__positioner", sideOffset: 4, children: _jsxs(BaseCombobox.Popup, { className: "select__popup select__popup--searchable", children: [_jsx(BaseCombobox.Input, { className: "select__search-input", placeholder: searchPlaceholder, "aria-label": searchAriaLabel, "data-test": dataTest ? `${dataTest}-search` : "select-search" }), _jsx(BaseCombobox.Empty, { className: "select__empty", children: "No matching options." }), _jsx(BaseCombobox.List, { className: "select__list select__list--searchable", children: (group) => (_jsxs(BaseCombobox.Group, { className: "select__group", items: group.items, children: [group.label ? (_jsx(BaseCombobox.GroupLabel, { className: "select__group-label", children: group.label })) : null, _jsx(BaseCombobox.Collection, { children: (item) => {
41
+ const triggerClassName = `select${iconOnly ? " select--icon-only" : ""}${compact ? " select--compact" : ""}${appearance === "embedded" ? " select--embedded" : ""}${className ? ` ${className}` : ""}`;
42
+ return (_jsxs(BaseCombobox.Root, { value: value || null, disabled: disabled, items: searchableGroups, itemToStringLabel: (item) => optionByValue.get(item)?.label ?? item, autoHighlight: true, onValueChange: handleValueChange, children: [_jsxs(BaseCombobox.Trigger, { ...triggerProps, render: iconOnly ? _jsx(IconButton, { label: props["aria-label"] ?? "Select option" }) : undefined, "data-test": dataTest, disabled: disabled, className: triggerClassName, children: [_jsx("span", { className: "select__value", children: _jsx(BaseCombobox.Value, { placeholder: placeholder, children: selectedOption?.label ?? (value || undefined) }) }), _jsx(BaseCombobox.Icon, { className: "select__icon", children: _jsx(IconChevronDown, { size: 15, stroke: 1.8, "aria-hidden": "true" }) }), children] }), _jsx(BaseCombobox.Portal, { container: portalContainer(), children: _jsx(BaseCombobox.Positioner, { className: "select__positioner", sideOffset: 4, side: popupPosition?.side, align: popupPosition?.align, children: _jsxs(BaseCombobox.Popup, { className: "select__popup select__popup--searchable", children: [_jsx(BaseCombobox.Input, { className: "select__search-input", placeholder: searchPlaceholder, "aria-label": searchAriaLabel, "data-test": dataTest ? `${dataTest}-search` : "select-search" }), _jsx(BaseCombobox.Empty, { className: "select__empty", children: "No matching options." }), _jsx(BaseCombobox.List, { className: "select__list select__list--searchable", children: (group) => (_jsxs(BaseCombobox.Group, { className: "select__group", items: group.items, children: [group.label ? (_jsx(BaseCombobox.GroupLabel, { className: "select__group-label", children: group.label })) : null, _jsx(BaseCombobox.Collection, { children: (item) => {
47
43
  const option = optionByValue.get(item);
48
44
  return option ? _jsx(SearchableSelectItem, { option: option }, item) : null;
49
45
  } })] }, group.value)) })] }) }) })] }));