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.
- package/README.md +164 -46
- package/dist/client.mjs +260 -61
- package/dist/css/value-semantics/colorSemantics.d.ts +4 -0
- package/dist/css/value-semantics/colorSemantics.js +17 -0
- package/dist/hosts/astro/astroRuntimeConfig.js +1 -0
- package/dist/hosts/astro/clientTransport.js +38 -32
- package/dist/hosts/astro/integration.js +5 -1
- package/dist/hosts/astro/markdownIdentity.d.ts +28 -0
- package/dist/hosts/astro/markdownIdentity.js +81 -0
- package/dist/hosts/next/manifest.js +1 -1
- package/dist/hosts/next/sidecar.js +5 -1
- package/dist/hosts/static/manifest.js +1 -1
- package/dist/hosts/static/server.js +3 -0
- package/dist/hosts/vite/vite.d.ts +3 -0
- package/dist/hosts/vite/vite.js +24 -4
- package/dist/inspector/agent/McpConnectionDialog.js +13 -19
- package/dist/inspector/agent/activity.d.ts +18 -0
- package/dist/inspector/agent/activity.js +70 -0
- package/dist/inspector/agent/client.d.ts +2 -0
- package/dist/inspector/agent/client.js +29 -1
- package/dist/inspector/agent/connectionStatus.js +1 -1
- package/dist/inspector/agent/httpTransport.js +9 -2
- package/dist/inspector/agent/protocol.d.ts +6 -3
- package/dist/inspector/agent/protocol.js +1 -1
- package/dist/inspector/agent/verification.d.ts +15 -7
- package/dist/inspector/agent/verification.js +113 -41
- package/dist/inspector/canvas/AgentActivityOverlay.d.ts +13 -0
- package/dist/inspector/canvas/AgentActivityOverlay.js +111 -0
- package/dist/inspector/canvas/CanvasCard.d.ts +9 -2
- package/dist/inspector/canvas/CanvasCard.js +135 -38
- package/dist/inspector/canvas/CanvasElementOverlay.js +166 -16
- package/dist/inspector/canvas/CanvasToolIcons.d.ts +10 -0
- package/dist/inspector/canvas/CanvasToolIcons.js +20 -0
- package/dist/inspector/canvas/CanvasToolbar.js +8 -4
- package/dist/inspector/canvas/CanvasWorkspace.js +270 -122
- package/dist/inspector/canvas/StaleChangeIndicator.js +3 -13
- package/dist/inspector/canvas/agentPresentation.d.ts +8 -8
- package/dist/inspector/canvas/agentPresentation.js +64 -52
- package/dist/inspector/canvas/canvasGestures.d.ts +1 -1
- package/dist/inspector/canvas/canvasGestures.js +1 -1
- package/dist/inspector/canvas/canvasStore.d.ts +46 -82
- package/dist/inspector/canvas/canvasStore.js +251 -284
- package/dist/inspector/canvas/frameContent.d.ts +21 -0
- package/dist/inspector/canvas/frameContent.js +44 -0
- package/dist/inspector/canvas/frameProtocol.d.ts +21 -4
- package/dist/inspector/canvas/frameProtocol.js +3 -3
- package/dist/inspector/canvas/frameScrollbarStyles.d.ts +3 -0
- package/dist/inspector/canvas/frameScrollbarStyles.js +21 -0
- package/dist/inspector/canvas/keyboardShortcuts.d.ts +3 -1
- package/dist/inspector/canvas/keyboardShortcuts.js +4 -4
- package/dist/inspector/canvas/layout.d.ts +52 -0
- package/dist/inspector/canvas/layout.js +106 -0
- package/dist/inspector/canvas/projection.d.ts +15 -5
- package/dist/inspector/canvas/projection.js +69 -13
- package/dist/inspector/canvas/rendererBootstrap.js +32 -4
- package/dist/inspector/canvas/rendererElementSelector.js +47 -6
- package/dist/inspector/canvas/rendererStylesheet.js +2 -2
- package/dist/inspector/canvas/resizeHandleScale.js +1 -1
- package/dist/inspector/canvas/sessionStore.d.ts +11 -26
- package/dist/inspector/canvas/sessionStore.js +43 -183
- package/dist/inspector/canvas/staleChangeDetector.js +9 -3
- package/dist/inspector/canvas/useCanvasLayoutAnimation.d.ts +5 -0
- package/dist/inspector/canvas/useCanvasLayoutAnimation.js +107 -0
- package/dist/inspector/canvas/viewStore.d.ts +38 -0
- package/dist/inspector/canvas/viewStore.js +104 -0
- package/dist/inspector/canvas/wheelPan.d.ts +8 -0
- package/dist/inspector/canvas/wheelPan.js +8 -0
- package/dist/inspector/changes/changesLog.d.ts +9 -6
- package/dist/inspector/changes/changesLog.js +48 -32
- package/dist/inspector/changes/codecs.d.ts +1 -0
- package/dist/inspector/changes/codecs.js +10 -1
- package/dist/inspector/changes/draftChanges.d.ts +58 -0
- package/dist/inspector/changes/draftChanges.js +304 -0
- package/dist/inspector/changes/editModel.d.ts +10 -0
- package/dist/inspector/changes/editModel.js +9 -2
- package/dist/inspector/changes/previewDiagnostics.d.ts +4 -2
- package/dist/inspector/changes/previewDiagnostics.js +11 -25
- package/dist/inspector/changes/types.d.ts +7 -0
- package/dist/inspector/clientManifest.d.ts +1 -1
- package/dist/inspector/comments/CommentsOverlay.d.ts +2 -0
- package/dist/inspector/comments/CommentsOverlay.js +250 -0
- package/dist/inspector/comments/element.d.ts +6 -0
- package/dist/inspector/comments/element.js +54 -0
- package/dist/inspector/comments/store.d.ts +29 -0
- package/dist/inspector/comments/store.js +121 -0
- package/dist/inspector/comments/verification.d.ts +5 -0
- package/dist/inspector/comments/verification.js +52 -0
- package/dist/inspector/componentSemantics/adapterRegistry.d.ts +6 -1
- package/dist/inspector/componentSemantics/adapterRegistry.js +23 -1
- package/dist/inspector/componentSemantics/reactRuntime.d.ts +2 -1
- package/dist/inspector/componentSemantics/reactRuntime.js +38 -0
- package/dist/inspector/componentSemantics/runtimeBridge.d.ts +4 -2
- package/dist/inspector/componentSemantics/runtimeBridge.js +17 -0
- package/dist/inspector/componentSemantics/types.d.ts +11 -0
- package/dist/inspector/drafts/model.d.ts +35 -0
- package/dist/inspector/drafts/model.js +45 -0
- package/dist/inspector/drafts/store.d.ts +28 -0
- package/dist/inspector/drafts/store.js +231 -0
- package/dist/inspector/index.js +20 -27
- package/dist/inspector/inline-text/inlineTextEditor.js +7 -0
- package/dist/inspector/inspection/useBrowserCssInspection.js +15 -1
- package/dist/inspector/iterations/capture.d.ts +2 -0
- package/dist/inspector/iterations/capture.js +174 -0
- package/dist/inspector/iterations/client.d.ts +7 -0
- package/dist/inspector/iterations/client.js +52 -0
- package/dist/inspector/iterations/coordinator.d.ts +15 -0
- package/dist/inspector/iterations/coordinator.js +130 -0
- package/dist/inspector/iterations/prompt.d.ts +3 -0
- package/dist/inspector/iterations/prompt.js +26 -0
- package/dist/inspector/overlay/DomNavigator.js +21 -15
- package/dist/inspector/overlay/interactionStyles.js +3 -1
- package/dist/inspector/overlay/spacingGestures.d.ts +13 -1
- package/dist/inspector/overlay/spacingGestures.js +82 -5
- package/dist/inspector/projection/{workspaceProjection.d.ts → draftProjection.d.ts} +6 -6
- package/dist/inspector/projection/{workspaceProjection.js → draftProjection.js} +4 -4
- package/dist/inspector/projection/renderedInstance.d.ts +17 -3
- package/dist/inspector/projection/renderedInstance.js +62 -11
- package/dist/inspector/projection/structuralProjection.d.ts +2 -1
- package/dist/inspector/projection/structuralProjection.js +21 -17
- package/dist/inspector/projection/textProjection.d.ts +2 -1
- package/dist/inspector/projection/textProjection.js +64 -15
- package/dist/inspector/prompt/PromptSettingsDialog.js +1 -5
- package/dist/inspector/prompt/clipboardHandoff.d.ts +15 -18
- package/dist/inspector/prompt/clipboardHandoff.js +97 -143
- package/dist/inspector/prompt/generatePrompt.d.ts +4 -1
- package/dist/inspector/prompt/generatePrompt.js +22 -17
- package/dist/inspector/runtime/runtimeConfig.d.ts +9 -0
- package/dist/inspector/runtime/runtimeConfig.js +24 -0
- package/dist/inspector/selection/sourceSite.d.ts +12 -0
- package/dist/inspector/selection/sourceSite.js +28 -0
- package/dist/inspector/settings/SettingsDialog.js +21 -8
- package/dist/inspector/shell/AgentStatusButton.d.ts +11 -0
- package/dist/inspector/shell/AgentStatusButton.js +36 -0
- package/dist/inspector/shell/AppShell.js +4 -2
- package/dist/inspector/shell/ChangesLog.js +46 -26
- package/dist/inspector/shell/CopyPromptButton.js +184 -93
- package/dist/inspector/shell/EmptyState.js +9 -8
- package/dist/inspector/shell/InspectorShell.js +13 -21
- package/dist/inspector/shell/PeekOriginalButton.js +24 -23
- package/dist/inspector/shell/originalPreview.js +5 -5
- package/dist/inspector/shell/shortcuts.d.ts +3 -0
- package/dist/inspector/shell/shortcuts.js +11 -0
- package/dist/inspector/sketch/SketchEditor.js +14 -14
- package/dist/inspector/sketch/SketchEntryButton.js +1 -1
- package/dist/inspector/sketch/SketchFrameOverlay.d.ts +3 -1
- package/dist/inspector/sketch/SketchFrameOverlay.js +11 -8
- package/dist/inspector/sketch/SketchLayersPanel.js +13 -5
- package/dist/inspector/sketch/SketchOverlay.js +7 -7
- package/dist/inspector/sketch/SketchWorkspace.js +18 -12
- package/dist/inspector/sketch/interaction.d.ts +1 -0
- package/dist/inspector/sketch/interaction.js +8 -4
- package/dist/inspector/sketch/model.d.ts +5 -0
- package/dist/inspector/sketch/model.js +6 -2
- package/dist/inspector/sketch/raster.d.ts +1 -2
- package/dist/inspector/sketch/raster.js +68 -4
- package/dist/inspector/styleEditors/BackgroundEditor.d.ts +4 -0
- package/dist/inspector/styleEditors/BackgroundEditor.js +195 -0
- package/dist/inspector/styleEditors/BorderEditor.js +49 -78
- package/dist/inspector/styleEditors/BorderRadiusEditor.js +6 -1
- package/dist/inspector/styleEditors/BoxShadowEditor.d.ts +1 -2
- package/dist/inspector/styleEditors/BoxShadowEditor.js +132 -4
- package/dist/inspector/styleEditors/ColorPicker.d.ts +5 -1
- package/dist/inspector/styleEditors/ColorPicker.js +10 -4
- package/dist/inspector/styleEditors/GapField.js +3 -5
- package/dist/inspector/styleEditors/GridChildSection.d.ts +1 -1
- package/dist/inspector/styleEditors/GridChildSection.js +18 -9
- package/dist/inspector/styleEditors/GridPicker.d.ts +1 -1
- package/dist/inspector/styleEditors/GridPicker.js +8 -2
- package/dist/inspector/styleEditors/GridSection.js +1 -1
- package/dist/inspector/styleEditors/GridValueField.js +19 -14
- package/dist/inspector/styleEditors/ImageBackgroundEditor.d.ts +18 -0
- package/dist/inspector/styleEditors/ImageBackgroundEditor.js +118 -0
- package/dist/inspector/styleEditors/LayoutBlockedIndicator.d.ts +2 -2
- package/dist/inspector/styleEditors/LayoutBlockedIndicator.js +3 -3
- package/dist/inspector/styleEditors/LayoutComboField.js +6 -4
- package/dist/inspector/styleEditors/LayoutDropdown.js +6 -3
- package/dist/inspector/styleEditors/LayoutSection.js +32 -11
- package/dist/inspector/styleEditors/SpacingBox.js +7 -5
- package/dist/inspector/styleEditors/Typography.js +11 -3
- package/dist/inspector/styleEditors/backgroundLayers.d.ts +24 -0
- package/dist/inspector/styleEditors/backgroundLayers.js +51 -0
- package/dist/inspector/styleEditors/gradientValue.d.ts +17 -0
- package/dist/inspector/styleEditors/gradientValue.js +114 -0
- package/dist/inspector/styleEditors/inlineAuthored.d.ts +10 -0
- package/dist/inspector/styleEditors/inlineAuthored.js +114 -0
- package/dist/inspector/styleEditors/layoutValue.d.ts +0 -8
- package/dist/inspector/styleEditors/layoutValue.js +0 -42
- package/dist/inspector/styleEditors/nudgeValue.d.ts +2 -2
- package/dist/inspector/styleEditors/nudgeValue.js +36 -8
- package/dist/inspector/tokens/TokenField.d.ts +7 -0
- package/dist/inspector/tokens/TokenField.js +35 -25
- package/dist/inspector/tokens/TokenLabel.js +5 -14
- package/dist/inspector/tokens/editActions.d.ts +1 -1
- package/dist/inspector/tokens/editActions.js +7 -1
- package/dist/inspector/ui/AtRuleContext.js +4 -6
- package/dist/inspector/ui/Button.d.ts +6 -2
- package/dist/inspector/ui/Button.js +4 -3
- package/dist/inspector/ui/ControlSurface.d.ts +2 -2
- package/dist/inspector/ui/ControlSurface.js +4 -3
- package/dist/inspector/ui/InlineStyleWarning.d.ts +11 -0
- package/dist/inspector/ui/InlineStyleWarning.js +13 -0
- package/dist/inspector/ui/InspectorPopover.d.ts +2 -1
- package/dist/inspector/ui/InspectorPopover.js +4 -5
- package/dist/inspector/ui/PopoverListbox.d.ts +2 -1
- package/dist/inspector/ui/PopoverListbox.js +8 -7
- package/dist/inspector/ui/SegmentedControl.d.ts +2 -1
- package/dist/inspector/ui/SegmentedControl.js +2 -2
- package/dist/inspector/ui/Select.d.ts +6 -1
- package/dist/inspector/ui/Select.js +7 -11
- package/dist/inspector/ui/SideValuesField.js +1 -1
- package/dist/inspector/ui/Tooltip.d.ts +26 -0
- package/dist/inspector/ui/Tooltip.js +32 -0
- package/dist/inspector/ui/classNames.d.ts +2 -0
- package/dist/inspector/ui/classNames.js +4 -0
- package/dist/inspector/ui/customCursors.d.ts +23 -0
- package/dist/inspector/ui/customCursors.js +122 -0
- package/dist/inspector/ui/dragCursor.d.ts +0 -2
- package/dist/inspector/ui/dragCursor.js +2 -10
- package/dist/inspector/ui/portalContainer.d.ts +2 -0
- package/dist/inspector/ui/portalContainer.js +6 -0
- package/dist/inspector/ui/styles.js +29 -21
- package/dist/inspector/workspace/commands.d.ts +9 -0
- package/dist/inspector/workspace/commands.js +82 -0
- package/dist/inspector/workspace/controller.d.ts +4 -0
- package/dist/inspector/workspace/controller.js +66 -0
- package/dist/inspector/workspace/handoff.d.ts +42 -0
- package/dist/inspector/workspace/handoff.js +115 -0
- package/dist/inspector/workspace/sentItems.d.ts +19 -0
- package/dist/inspector/workspace/sentItems.js +51 -0
- package/dist/inspector/workspace/timeline.d.ts +30 -0
- package/dist/inspector/workspace/timeline.js +108 -0
- package/dist/internal/agent-protocol.d.ts +19 -2
- package/dist/internal/agent-protocol.js +13 -0
- package/dist/nudge-ui.mjs +558 -311
- package/dist/project/artifacts.d.ts +13 -0
- package/dist/project/artifacts.js +253 -0
- package/dist/transport/artifacts.d.ts +8 -0
- package/dist/transport/artifacts.js +9 -0
- package/dist/transport/editor.js +3 -1
- package/dist/transport/routes.d.ts +2 -0
- package/dist/transport/routes.js +2 -0
- package/package.json +7 -3
- package/dist/inspector/changes/workspaceChanges.d.ts +0 -47
- 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/
|
|
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
|
|
104
|
-
|
|
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 `#${
|
|
107
|
-
.map((
|
|
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(
|
|
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 (
|
|
348
|
+
if (fieldDisabled || !supportsDragNudge(nudgeProperty))
|
|
340
349
|
return;
|
|
341
|
-
if (!canNudgeCssValueByDrag(
|
|
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(
|
|
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 = !
|
|
413
|
-
&& supportsDragNudge(
|
|
414
|
-
&& canNudgeCssValueByDrag(
|
|
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,
|
|
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:
|
|
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:
|
|
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:
|
|
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:
|
|
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:
|
|
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:
|
|
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
|
-
|
|
3
|
-
|
|
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:
|
|
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
|
-
|
|
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,
|
|
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,
|
|
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
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
2
|
import { createContext, useContext, useMemo } from "react";
|
|
3
|
-
import { Tooltip } from "
|
|
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
|
|
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
|
|
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
|
|
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
|
-
|
|
3
|
-
|
|
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,
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
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:
|
|
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: [
|
|
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:
|
|
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,
|
|
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
|
|
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)) })] }) }) })] }));
|